簡體   English   中英

為什么大多數推送通知都無法到達設備

[英]Why most push notifications fail to reach the device

不確定與iPhone SDK推送通知是否相同,是否會隨機失敗 但是確實有一些通知到達,當對命令8數據包進行加擾時,我確實做了“拆包”警告。

我有一個php文件,該文件從具有令牌,有效負載和設備(iphone,ipad)的表(DB)中提取所有通知。 此php每15秒在服務器cron上運行一次。 我不知道為什么有時有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);
                }
            }
        }
    }


?>

我對upack命令8個數據包確實有“拆包”警告

這意味着您正在從Apple獲得錯誤響應,但是從我在代碼中看到的結果來看,除了記錄這些錯誤之外,您對這些錯誤沒有做任何事情。 每個此類錯誤響應都意味着您向Apple發送了無效數據,結果Apple關閉了連接。 這意味着在無效消息之后發送的任何消息都將被丟棄,直到您打開新連接為止。

處理此類響應的正確方法是解析其中包含的錯誤消息ID,打開與APNS的新連接,然后重新發送在錯誤消息之后發送的所有消息。

最可能的錯誤是無效的設備令牌。 當您將開發令牌發送到生產推送環境時,通常會發生這種情況,反之亦然。 如果您從數據庫中清除了無效的設備令牌,則很可能會看到100%的消息到達。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM