蛋疼的Apple IOS Push通知协议
简介
Apple Push通知机制其实很简单,就是Apple的APNs服务器做为中间人,把消息推送到对应的设备上。
一张来自Apple文档的图:
当然,示意图看起来简单,但是还有一些实际的问题。
比如,如何区分Provicer的?如何区分设备的?
简单而言,是这样的:
- 每个应用都有一个自己的证书(certificate),开发者可以从苹果那里获得;
- 应用可以到APNs服务器上注册(register),然后得到一个device_token,开发者要自己保存好,推送时就要用这个来区分不同的设备。
- 注意,token并不是设备唯一标识码。token是可以改变的,因此APNs提供了一个feedback服务,开发者可以得到失效的token。
- 对于每个设备只存储最后的一条push,所以如果连续发很多条push,设备没有及时接收的话,后面的push会覆盖前面的。
- Provider和APNs服务器,APNs服务器和用户设备之间的通迅都是SSL/TLS协议的。这点要比国内的推送服务商要做的好,国内的推送服务都是http接口的,完全没有加密。
- Push都是对于设备而言的。所以敏感信息不要通过push来传递。
- Push是尽量送达的,Push消息可能会丢失,所以不要用Push来传递可靠数据。
Apple Push的协议蛋疼之处
上面只是有一些要注意的小地方,下面来说下真正蛋疼的东西:Apple Push的协议。
首先,明显的是设计不良:
协议里的command,现在实际上也用来表示Version。
比如command = 0, 1, 2就分别表示发送消息的三个版本。
更蛋疼的是前面0,1两个版本现在的文档都找不到了。这个让维护老代码的人情何以堪?想调试下bug,结果发现官方文档都消失了,那得多蛋疼。
Apple的文档里只说到:
Field name |
Length |
Discussion |
---|---|---|
Command |
1 byte |
Populate with the number |
可能在你看这篇文章的时候,变成了“Populate with the number 3”了。。
正常人看到这里只会觉得一头雾水,为什么这个command是2?怎么想得到这个Command居然是和版本相关的。。我是从别的一些实现代码里才知道有三个版本的。
协议格式混乱
比如这个feedback的格式:
deviceToken就是固定好了是32字节的,前面还要加一个Token length。
有人可能说,这是考虑了以后token大于32字节的。那干脆应该为feedback的回应包加上版本号。
发送者可以批量发送消息,但是只有出错的时候才会返回出错消息的ID。
这个乍看起来,没什么问题。但是当你想要实现一个Push客户端的时候,就知道蛋疼之处了:
发送者连续发了1,2,3,4 ... 100 条消息,已经写到socket里去了,这里APNs服务器回应说第57条消息失败了。
那发送者得从第58条开始,重新再发。那发送者得把前面已经发送出去了的消息缓存起来!
好的,缓存一下也没关系,那么到底缓存多少个消息呢?1024个?2048个?天知道。
要是发送者的网速快,一下子把4096个消息都发出去了呢?那怎么办?
好吧,也许你会说4096个消息体比较大小,Apple的服务器的TCP socket缓冲区都满了,你发不了这么多的消息。
我只是想发个Push消息而已,难道还要推算APNs服务器的socket缓冲区的大小?要是它的网络框架也做了缓冲呢?要是发送者的网络框架也做了缓冲呢?
是不是每次发送时,都要等待数据全都写到socket里去了?
开发者测试用的沙箱服务器是个摆设
文档上写了在开发环境可以用这个域名,gateway.sandbox.push.apple.com。但是坑爹的是,这个域名实际上是个摆设,你可以建立SSL连接,也可以正常发送消息。
但是你的设备却是收不到消息的。要是在实现自己的客户端时,用这个来测试,就蛋疼了,一次次检查自己的代码,看是否有问题,最终却发现是对方的服务器有问题。。
只有程序员才能明白这种蛋疼的心情。
不支持分组发送
现在的国内流行的推送服务,如百度推送等,都支持分组的配置,这样大大节省了带宽,提离了发送效率。
可能还有一些蛋疼的地方,忘记了,下篇blog说下一些实现自己的客户端要注意的事项及一个Java的实现ZPush。
参考:
http://support.apple.com/kb/HT3576?viewlocale=zh_CN&locale=zh_CN
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW12
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW1