不确定它是否与iPhone SDK Push notification randomly fails相同。但是有些通知确实到了,我确实有#34; unpack" upacking命令8包时发出警告。
我有一个php文件,它从包含令牌,有效负载和设备(iphone,ipad)的表(DB)中提取任何通知。这个php在服务器cron上每15秒运行一次。我不知道为什么20%的通知有时会到达....有时80%到达....有时没有到达(我有10个设备用于测试)。我读到苹果通知是"尽力而为"并且没有保证到达,但这很荒谬,我的代码逻辑肯定是错的。这是我的代码,出于隐私原因,我更改了目录,数据库信息和文件的名称。请帮忙。
<?php
include("/#####/DB.conf");
$link = mysql_connect($host,$userDB,$passDB) or die("Failed to connect: " . mysql_error());
mysql_select_db('#######') or die("Failed to connect: " . mysql_error());
mysql_query("SET NAMES 'utf8'");
$certFile_iphone = '/##########/push_production.pem';
$certFile_ipad = '/########/push_production.pem';
$passphrase = '#########';
$sent += sendPush($certFile_iphone,$passphrase,'iphone');
$borrados += checkFeedback($certFile_iphone,$passphrase,'iphone');
$sent += sendPush($certFile_ipad,$passphrase,'ipad');
$borrados += checkFeedback($certFile_ipad,$passphrase,'ipad');
//////////////////////////////
//Send notification to users//
//////////////////////////////
function sendPush($cert,$pass,$device)
{
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $cert);
stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);
// Open a connection to the APNS server
$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 600, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
//gets all the devices of that type and their current notification to send
$query = mysql_query("SELECT * FROM pushNotification_buffer WHERE device = '".$device."' LIMIT 1000;");
$errors = 0;
$sent = 0;
$i = 0;
while($row = mysql_fetch_array($query))
{
$payload = $row['payload'];
$deviceToken = $row['identificador'];
//$msg = chr(0) . pack('n', 32) . pack('H*', $row['identificador']) . pack('n', strlen($payload)) . $payload;
$msgInner =
chr(1)
. pack('n', 32)
. pack('H*', $deviceToken)
. chr(2)
. pack('n', strlen($payload))
. $payload
. chr(3)
. pack('n', 4)
. chr($i)
. chr(4)
. pack('n', 4)
. pack('N', time() + 86400)
. chr(5)
. pack('n', 1)
. chr(10)
;
$msg=
chr(2)
. pack('N', strlen($msgInner))
. $msgInner
;
$i++;
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
{
$errors++;
usleep(1000000);
$result = fwrite($fp, $msg, strlen($msg));
error_log("Error on Device (2): " . $row['identificador']);
}
if (!$result)
{
$errors++;
fclose($fp);
return $sent;
}
else
{
$sent++;
mysql_query("DELETE FROM pushNotification_buffer WHERE identificador = '".$row['identificador']."' AND payload = '".mysql_real_escape_string($row['payload'])."' LIMIT 1;");
}
error_response($fp);
}
fclose($fp);
return $sent;
}
/////////////////
//APNS FeedBack//
/////////////////
function checkFeedback($cert,$pass,$device){
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $cert);
stream_context_set_option($ctx, 'ssl', 'verify_peer', false);
stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);
$fp = stream_socket_client('ssl://feedback.push.apple.com:2196', $error, $errorString, 600, STREAM_CLIENT_CONNECT, $ctx);
$toDelete = 0;
if(!$fp) echo ("NOTICE: Failed to connect to device: $error - $errorString.");
while ($devcon = fread($fp, 38)){
$arr = unpack("H*", $devcon);
$rawhex = trim(implode("", $arr));
$token = substr($rawhex, 12, 64);
if(!empty($token))
{
if($device == 'iphone'){
mysql_query("DELETE FROM iphoneDevicesAPNS WHERE identificador = '" . $token . "' LIMIT 1;");
}else{
mysql_query("DELETE FROM ipadDevicesAPNS WHERE identificador = '" . $token . "' LIMIT 1;");
}
$toDelete++;
}
}
fclose($fp);
return $toDelete;
}
/////////////////////////////
//Error response, command 8//
/////////////////////////////
function error_response($fp){
$read = array($fp);
$null = null;
$changedStreams = stream_select($read, $null, $null, 0, 1000000);
if ($changedStreams === false)
{
echo ("Error: Unabled to wait for a stream availability");
}
elseif ($changedStreams > 0){
$responseBinary = fread($fp, 6);
if ($responseBinary !== false || strlen($responseBinary) == 6){
$response = unpack('Ccommand/Cstatus_code/Nidentifier', $responseBinary);
var_dump($response);
if (strlen($response["command"] > 0) || strlen($response["status_code"] > 0) || strlen($response["identifier"] > 0)){
$texto=
"------------------------------------------". "\n".date("Y-m-d G:i:s"). "\n";
"id: " . $response["identifier"] . "\n" .
"code: ". $response["status_code"] . "\n" .
"command: ". $response["command"] . "\n". "\n"
;
file_put_contents ( "/#####/logAPNS.log" ,$texto, FILE_APPEND);
}
}
}
}
?>
答案 0 :(得分:0)
我确实有&#34;解包&#34; upacking command 8 packets时的警告
这意味着您收到来自Apple的错误回复,但是从我在代码中看到的内容,除了记录这些错误之外,您不会对这些错误做任何事情。每个此类错误响应都意味着您向Apple发送了无效数据,因此Apple关闭了连接。这意味着在无效之后发送的任何消息都将被丢弃,直到您打开新连接为止。
处理此类响应的正确方法是解析其中包含的错误消息ID,打开与APNS的新连接,并重新发送在错误消息之后发送的所有消息。
最可能的错误是设备令牌无效。这通常发生在您将开发令牌发送到生产推送环境时,反之亦然。如果您从数据库中清除了无效的设备令牌,您可能会看到100%的消息到达。