问题描述
我设置了一个推送通知服务,以根据 RSS 提要向客户端发送通知.我有一个每分钟运行一次的服务,以查看是否有新帖子添加到提要中.如果是这样,该服务将向所有客户端发送通知.但是,有些人一直在抱怨说他们没有收到任何推送通知.这是我用来发送消息的函数:
I set up a push notification service to send out notifications to clients based on an RSS feed. I have a service that runs every minute to see if a new post was added to the feed. If so, the service will send out a notification to all the clients. However, some people have been complaining saying that they are not receiving any push notifications. Here is the function that I use to send out the messages:
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 不能处理通过这个 for 循环数千次并通过连接流式传输消息吗?
Am I doing anything wrong? Can PHP not handle going through this for loop thousands of times and streaming messages over the connection?
推荐答案
除了其他人已经提出的建议之外,这里有一份在推送不起作用时需要考虑的事项清单.
Other than the suggestions already made by others, here's a checklist of things to consider when pushes don't work.
- 如果您的总推送数据包超过 256 字节,包括初始标头、令牌和 JSON 有效负载,APNS 将简单地丢弃它.如果您没有使用高级"错误检测,您将永远不会知道,直到您的用户开始抱怨.您需要做的是检查编码的数据包大小,即您将在线路上抽取的实际数据的大小,如果超过 256 字节,要么拒绝它,要么截掉一些消息文本并进行编码再重复一次,直到
- 如果您的有效载荷有任何问题,包括长度,APNS 会丢弃它,APNS 也会丢弃您的连接.
- 如果你有一个持久的连接,并且空闲了大约 20 分钟左右,APNS 会默默地断开连接.您必须为此做好准备并重新连接.
- 如果您的 APNS 证书已过期或不正确,并且您继续以过高的速率尝试连接,APNS 会将您的 IP 地址列入黑名单一段未知的时间,但时间远不止几分钟,甚至可能是小时或更长时间.
- 如果 iPhone 没有 3G 接收功能,但有 WiFi,它会尝试将其用于推送通知.如果您位于不允许出站连接到 Apple 网络的防火墙区域,您的 iPhone 将无法打开到 APNS 的套接字,而您就是 SOL.
- 我不确定您的 SQL 数据库是否在每次客户端连接到 APNS 时使用推送令牌进行更新.拥有推送令牌的静态数据库是一个问题,因为推送令牌不会永远保持不变——它甚至在 APNS 编程指南中也这么说.iPhone 应该在每次启动时获取推送令牌,并将其传达给服务器端(我相信您可以优化这一点 - iPhone 可以持久地存储最后一个令牌并仅在它发生更改时发送它).但是有些事情会导致推送令牌发生变化,例如重新注册iPhone进行推送,我不确定还有什么.我所知道的是,依赖推送令牌就像一个 GUID 是在自找麻烦.下次令牌更改时,如果您的数据库未更新,请告别推送到该客户端.
- If your total push packet exceeds 256 bytes, including the initial header, token, and JSON payload, APNS will simply drop it. If you are not using the "advanced" error detection, you will never know until your users start complaining. What you have to do is check the encoded packet size, that is, the size of the actual data you will pump down the wire, and if it's longer than 256 bytes, either reject it, or cut off some of the message text and encode it again until it is <= 256 bytes long.
- If there is anything wrong with your payload in any way, including the length, APNS will drop it, and APNS will drop your connection, too.
- If you have a persistent connection, and it is idle for about 20 minutes or so, APNS will silently drop the connection. You have to be prepared for that and reconnect.
- If your APNS certificate has expired or is incorrect, and you continue trying to connect at too high a rate, APNS will blacklist your IP address for an unknown period of time, but it's much more than a few minutes, maybe even an hour or more.
- If the iPhone does not have 3G reception, but does have WiFi, it will try to use that for push notifications. If you are in a firewalled area that does not allow outbound connections to Apple's network, your iPhone will not be able to open a socket to APNS and you are SOL.
- I am not sure if your SQL DB is updated with push tokens every time a client connects to APNS. Having a static database of push tokens is an issue, because push tokens don't stay the same forever - it even says so in the APNS programming guide. The iPhone is supposed to get the push token each time it launches, and communicate it to the server side (and I am sure you can optimize this - the iPhone could store the last token persistently and send it only if it has changed). But some things can cause the push token to change, such as re-registering the iPhone for push, and I am not sure what else. All I know is that relying on a push token to be like a GUID is asking for trouble. The next time the token changes, if your DB is not updated, goodbye push to that client.
希望这会有所帮助.
这篇关于为什么只有某些设备会收到推送通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!