同时发送5000个推送通知,保持与Apple打开的连接?

Mar*_*ark 5 php iphone push-notification apple-push-notifications ios

现在我正在使用以下代码发送推送通知

function applePush($deviceToken,$sound,$message,$object,$thread = 0)
{
$passphrase = 'Secret';


        $ctx = stream_context_create();
        stream_context_set_option($ctx, 'ssl', 'local_cert', 'secret.pem');
        stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);

        // Open a connection to the APNS server
        $fp = stream_socket_client(
            'ssl://gateway.push.apple.com:2195', $err,
            $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);

        if (!$fp)
            exit("Failed to connect: $err $errstr" . PHP_EOL);

        //Customizable sounds
        if ($sound == 0) { $sound = 'default'; }
        else {$sound = '/' . $sound . '.wav'; }         

        // Create the payload body
        if ($thread > 0)
            {

                    $body['aps'] = array(
                        'alert' => $message,
                        'sound' => $sound,
                        'obj' => $object,
                        't' => $thread,
                        );

            }
        else
            {
                    $body['aps'] = array(
                        'alert' => $message,
                        'sound' => $sound,
                        'obj' => $object
                        );

            }   


        // Encode the payload as JSON
        $payload = json_encode($body);

        // Build the binary notification
        $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;

        // Send it to the server
        $result = fwrite($fp, $msg, strlen($msg));


        // Close the connection to the server
        fclose($fp);

}
Run Code Online (Sandbox Code Playgroud)

我本质上在做的是:1)从SQL数据库中提取5000(并且正在增长)设备令牌.
2)使用PHP循环,为每个设备令牌运行上面列出的applePush函数

现在这个工作得很好,每个人都从苹果那里得到了推动.现在踢球者,我自己的个人iphone是我的SQL数据库中的第一个设备,我会立即获得推送通知. 但是,我刚刚买了一台新的iphone,我现在是数据库中的最后一台设备,我注意到现在需要花费近30分钟的时间来获取通知.我认为这与物理时间有关,使所有这些连接到苹果,但它到达第5000个设备ID的时间,30分钟已经失效.

这让我阅读,似乎Apple实际上建议保持与APNS的连接,而不是不断打开和关闭连接.

所以我写信是为了得到每个人的意见,我这样做是错的吗?如果我是,我如何修改我的代码以使其与Apple策略一致,并使其更快/更高效

谢谢!

med*_*eda 10

不要打开和关闭连接5000次,这是非常昂贵的,不可接受.

该问题与Android不同,Apple Server不会将一系列设备令牌与playload一起使用.

更好的方法是循环数据库并返回一个数组.

一旦连接打开,该数组将在循环中使用.

所以你会有这样的事情:

//Apple Push Notifcations
$apn = new Apple_Push_Notifications();

//Get Device tokens into an array
$deviceTokens = array();
$deviceTokens = $apn->GetDeviceTokens();

//Push the notifications
if(count($deviceTokens) > 0){
    $apn->applePush($deviceTokens,$sound,$message,$object,$thread);
}

//In applePush loop through all the tokens and submit
function applePush($deviceTokens,$sound,$message,$object,$thread = 0)
{
    ....
    // Open a connection to the APNS server
    $fp = stream_socket_client(
        'ssl://gateway.push.apple.com:2195', $err,
        $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
    ....
    ....
    // Encode the payload as JSON
    $payload = json_encode($body);

    //Send the Push to each token the close connection
    foreach ($deviceTokens as $deviceToken) {
        // Build the binary notification
        $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;

        // Send it to the server
        $result = fwrite($fp, $msg, strlen($msg));
    }

    // Close the connection to the server
    fclose($fp);
}
Run Code Online (Sandbox Code Playgroud)


Era*_*ran 2

您应该尽可能长时间地保持连接打开。提高性能的另一种方法是使用多个线程(每个线程都有自己的与 APN 服务器的连接,该服务器保持打开状态)并在它们之间划分发送推送通知的工作。

\n\n

在每条消息后关闭连接不仅会影响性能,而且如果 Apple 认为这是 DOS 攻击,还可能会禁止您的 IP。

\n\n
\n

在多个通知中保持与 APN 的连接处于打开状态;\n 不要\xe2\x80\x99t 重复打开和关闭连接。APN 将快速连接和断开连接视为拒绝服务攻击。您应该让连接保持打开状态,除非您知道连接将在较长一段时间内处于空闲状态\xe2\x80\x94例如,如果您每天只向用户发送一次通知,则可以使用每天都有新的连接。

\n
\n