为什么只有部分设备接收推送通知

时间:2010-11-10 04:44:35

标签: php iphone push-notification apple-push-notifications

我设置了推送通知服务,以根据RSS源向客户发送通知。我有一个每分钟运行一次的服务,看看是否有新帖子添加到Feed中。如果是这样,该服务将向所有客户发送通知。但是,有些人一直在抱怨说他们没有收到任何推送通知。这是我用来发送消息的功能:

function _sendMessages($tokens, $message) {
        $payload['aps'] = array('alert' => $message, 'sound' => 'default');
        $payload = json_encode($payload);

        $context = stream_context_create();
        stream_context_set_option($context, 'ssl', 'local_cert', $this->certificate);
        stream_context_set_option($context, 'ssl', 'passphrase', '*********');

        $apns = stream_socket_client('ssl://' . $this->server . ':' . $this->port, $error, $errorString,60, STREAM_CLIENT_CONNECT, $context);

        foreach($tokens as $row) {
            $apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $row->device_token)) . chr(0) . chr(strlen($payload)) . $payload;
            $fwrite = fwrite($apns, $apnsMessage);

            if (!$fwrite) echo 'push error';
            else echo 'push success';
        }

        fclose($apns);
    }

我做错了吗? PHP无法处理数千次循环并通过连接传输消息吗?

3 个答案:

答案 0 :(得分:5)

除了其他人已经提出的建议外,这里还有一个清单,列出了推送不起作用时要考虑的事项。

  1. 如果您的总推送数据包超过256个字节,包括初始标头,令牌和JSON有效负载,APNS将简单地丢弃它。如果您没有使用“高级”错误检测,您将永远不会知道,直到您的用户开始抱怨。你需要做的是检查编码的数据包大小,即你将抽取线路的实际数据的大小,如果它超过256字节,要么拒绝它,要么切断一些消息文本和编码它再次直到< = 256字节长。
  2. 如果你的有效载荷有任何问题,包括长度,APNS会丢弃它,APNS也会放弃你的连接。
  3. 如果您有持久连接,并且它闲置大约20分钟左右,APNS将默默地断开连接。你必须为此做好准备并重新连接。
  4. 如果您的APNS证书已过期或不正确,并且您继续尝试以过高的速率连接,APNS会将您的IP地址列入黑名单一段未知时间,但这可能会超过几分钟,甚至可能是小时或更长时间。
  5. 如果iPhone没有3G接收,但确实有WiFi,它会尝试将其用于推送通知。如果您所在的防火墙区域不允许与Apple网络的出站连接,则您的iPhone将无法打开APNS的套接字,而您就是SOL。
  6. 每次客户端连接到APNS时,我不确定您的SQL DB是否使用推送令牌进行更新。拥有推送令牌的静态数据库是一个问题,因为推送令牌永远不会保持不变 - 它甚至在APNS编程指南中都这样说。 iPhone应该在每次启动时获取推送令牌,并将其传送到服务器端(我相信你可以优化它 - iPhone可以持久存储最后一个令牌并仅在它已经改变时发送它)。但有些事情会导致推送令牌发生变化,例如重新注册iPhone以进行推送,而我不确定还有什么。我所知道的是,依赖推送令牌就像一个GUID就是在寻找麻烦。下次令牌更改时,如果您的数据库未更新,请再次推送到该客户端。
  7. 希望这有帮助。

答案 1 :(得分:1)

我认为这里存在3个潜在问题:

1)你经常连接(可能比你想象的更频繁),Apple拒绝/放弃连接,因为它认为你太垃圾了。说实话,这很明显 - 你的fwrite会因为流已经死了而失败。

APNS理想情况下,连接尽可能长时间保持打开状态(10分钟是我们使用的非活动超时),而不是每分钟重新建立一次。 SSL协商会耗费CPU,但保持打开的连接相对便宜。因此,如果可以的话,我会在运行之间保持连接打开,如果因任何原因被丢弃,我会自动重新建立连接。

2)您没有进行任何错误检查。请参阅APNS指南,但它可能会在错误响应的同一连接上回复,而您只是忽略了这一点。我认为每次循环你应该检查是否有任何数据要读取,读取它并将其解释为错误响应数据包。至少你应该记录错误响应。

3)这是一个很长的镜头。您是否有可能实际删除了这些用户,可能是因为反馈服务告诉您?如果用户长时间断开连接,服务将无法发送通知,并且可能会告诉您从列表中删除这些设备。如果您在应用程序启动时没有重新订阅这些用户(或者至少确认他们仍在订阅),那么他们会认为他们订阅了通知,而实际上您已经选择忘记这些通知。

答案 2 :(得分:0)

嗯......我没有看到任何问题。客户端是否实际为您的应用启用了推送通知?