带有 PHP 的 APNS 显示 SSL 损坏的管道错误
Posted
技术标签:
【中文标题】带有 PHP 的 APNS 显示 SSL 损坏的管道错误【英文标题】:APNS with PHP shows SSL broken pipe error 【发布时间】:2017-11-24 03:54:19 【问题描述】:在我的项目中,大约有 500 个 ios 用户。向他们发送推送通知会显示以下错误。
Severity: Warning
Message: fwrite(): SSL: Broken pipe
Message: fwrite(): SSL operation failed with code 1. OpenSSL Error messages:
error:1409F07F:SSL routines:ssl3_write_pending:bad write retry
直到某些令牌工作正确,结果为整数,例如 181,因为从结果为 0 的第一个令牌开始显示上述错误。是由于令牌无效吗?。我无法区分生产和开发令牌。请帮助。提前致谢。 我的代码
public function connectApns()
try
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert',$_SERVER['DOCUMENT_ROOT'].'/webservice/application/libraries/ck.pem');
stream_context_set_option($ctx, 'ssl','passphrase', '1234');
$this->fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err,$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if($this->fp)
return TRUE;
else
echo $errstr;
return FALSE;
catch(Exception $e1)
echo $e1->getMessage();
public function iOS($data,$columnName)
$ids = array();
$tokens = array();
$sql = "SELECT user_id FROM tp_notification WHERE ";
if($columnName == "job")
$sql = $sql." job = 1";
if($columnName == "hostel")
$sql = $sql." hostel = 1";
if($columnName == "event")
$sql = $sql." event = 1";
if($columnName == "bazar")
$sql = $sql." bazar = 1";
if($columnName == "share")
$sql = $sql." share = 1";
if($columnName == "court")
$sql = $sql." court = 1";
if($columnName == "contest")
$sql = $sql." contest = 1";
if($columnName == "")
$sql = "SELECT user_id FROM tp_notification";
$query = $this->CI->db->query($sql);
if($query)
$mid_result = $query->result_array();
foreach ($mid_result as $value)
$ids[] = $value['user_id'];
if(count($ids) > 0)
$sql1 = "SELECT device_token FROM tp_user WHERE user_id IN ? AND device_type = ? AND user_active = ? ORDER BY user_id DESC";
$query1 = $this->CI->db->query($sql1,array($ids,'iOS',1));
if($query1)
$mid_result1 = $query1->result_array();
foreach ($mid_result1 as $key)
$tokens[] = $key['device_token'];
if(count($tokens) > 0)
$isConnected = $this->connectApns();
if ($isConnected)
for($i = 0; $i < count($tokens); $i++)
$sql5 = "SELECT badge FROM tp_user WHERE device_token = ?";
$query5 = $this->CI->db->query($sql5,array($tokens[$i]));
$badge = 0;
if($query5)
$mid_result5 = $query5->row();
$badge = $mid_result5->badge + 1;
$body['aps'] = array(
'alert' => array(
'title' => $data['title'],
'body' => $data['data'],
'type'=>$data['type'],
'id'=>$data['id']
),
'content-available'=>1,
'badge'=>$badge,
'sound' => 'default'
);
$deviceToken = $tokens[$i];
$payload = json_encode($body);
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
try
if(strlen($deviceToken) == 64)
$result = fwrite($this->fp, $msg, strlen($msg));
if($result)
$sql6 = "UPDATE tp_user SET badge=? WHERE device_token=?";
$query6 = $this->CI->db->query($sql6,array($badge,$tokens[$i]));
else
fclose($this->fp);
sleep(5);
$this->connectApns();
catch(Exception $e)
fclose($this->fp);
sleep(3);
$this->connectApns();
fclose($this->fp);
【问题讨论】:
包含与您的问题相关的代码。 我的代码如上图 【参考方案1】:定义常量
define('Apple_HOST','gateway.push.apple.com');
define('Apple_API_NOTI',"abc.pem"); // write here path pem file
调用函数->
sendPushIos("write here device token",array('alert' =>$message, 'badge' => 1, 'sound' => 'default','flag'=>$flag))
ios通知发送功能->
function sendPushIos($dEvicetoken,$arrayY)
$apnsHost = Apple_HOST;
$apnsCert =Apple_API_NOTI;
$apnsPort = 2195;
$token=$dEvicetoken;
$streamContext = stream_context_create();
@stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
$payload['aps'] =$arrayY;
$output = json_encode($payload);
$token = pack('H*', str_replace(' ', '', $token));
$apnsMessage = chr(0) . chr(0) . chr(32) . $token . chr(0) . chr(strlen($output)) . $output;
if(fwrite($apns, $apnsMessage))
@socket_close($apns);
fclose($apns);
return TRUE;
else
return FALSE;
注意:2195端口必须打开
【讨论】:
很少有通知发送,对于那些结果大于0,然后结果变为0,然后显示ssl损坏管道错误。这个问题与SSL有关吗? 现在它可以工作了。我将 if(strlen($deviceToken)) 循环扩展到 try 的右括号之前。即到最后。以上是关于带有 PHP 的 APNS 显示 SSL 损坏的管道错误的主要内容,如果未能解决你的问题,请参考以下文章
Worklight 推送通知 (APNS) 失败并出现 javax.net.ssl.SSLHandshakeException