drwdvftp423507 2013-06-11 13:17
浏览 32
已采纳

PHP APNS一个令牌失败

I have a problem with APNS and an invalid token that "blocks" all following pushes. Here is a code sample in PHP :

$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $cert_path);
$fp = stream_socket_client($ssl_url, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $ctx);
stream_set_blocking($fp, 0);
stream_set_write_buffer($fp, 0);

if (!$fp) {
    while ($message = nextMessage()) {
        $msg = chr(0) . pack("n", 32) . pack('H*', $token) . pack("n", strlen($message)) . $message;
        $fwrite = fwrite($fp, $msg);
    }
    fclose($fp);
}

This code works perfectly

  • with one valid token (the device received the message)
  • with many valid token (all devices received the message)

Moreover, I don't want to open/close the stream socket for each message : it is too slow.

But if an invalid token is used, all the device FOLLOWING the invalid one won't receive the message. The Feedback Service doesn't tell me anything now (I may have received once the information that this token was invalid). Doing "while (!feof($fp)) fread($fp);" doesn't give me information.

Can you help me how to solve that problem?

Thank you.

  • 写回答

1条回答 默认 最新

  • dsgwii4867 2013-06-11 15:29
    关注

    That's the way Apple implemented their push notifications (very annoying). If you send an invalid token, they return an error response and close the socket. Until you discover that the socket was closed, you may have already sent many more messages, all of which have been discarded and need to be resent after you create a new socket.

    The feedback service won't help you there. It returns valid device tokens of devices on which your app is no longer installed. It doesn't return invalid tokens.

    Here's what Apple have to say about it :

    Push Notification Throughput and Error Checking

    There are no caps or batch size limits for using APNs. The iOS 6.1 press release stated that APNs has sent over 4 trillion push notifications since it was established. It was announced at WWDC 2012 that APNs is sending 7 billion notifications daily.

    If you're seeing throughput lower than 9,000 notifications per second, your server might benefit from improved error handling logic.

    Here's how to check for errors when using the enhanced binary interface. Keep writing until a write fails. If the stream is ready for writing again, resend the notification and keep going. If the stream isn't ready for writing, see if the stream is available for reading.

    If it is, read everything available from the stream. If you get zero bytes back, the connection was closed because of an error such as an invalid command byte or other parsing error. If you get six bytes back, that's an error response that you can check for the response code and the ID of the notification that caused the error. You'll need to send every notification following that one again.

    Once everything has been sent, do one last check for an error response.

    It can take a while for the dropped connection to make its way from APNs back to your server just because of normal latency. It's possible to send over 500 notifications before a write fails because of the connection being dropped. Around 1,700 notifications writes can fail just because the pipe is full, so just retry in that case once the stream is ready for writing again.

    Now, here's where the tradeoffs get interesting. You can check for an error response after every write, and you'll catch the error right away. But this causes a huge increase in the time it takes to send a batch of notifications.

    Device tokens should almost all be valid if you've captured them correctly and you're sending them to the correct environment. So it makes sense to optimize assuming failures will be rare. You'll get way better performance if you wait for write to fail or the batch to complete before checking for an error response, even counting the time to send the dropped notifications again.

    None of this is really specific to APNs, it applies to most socket-level programming.

    If your development tool of choice supports multiple threads or interprocess communication, you could have a thread or process waiting for an error response all the time and let the main sending thread or process know when it should give up and retry.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作