蛋疼的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。
參考:
https://developer.apple.com/library/ios/technotes/tn2265/_index.html 這個文檔很值得參考,說到了一些實現的要點。
https://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
最後更新:2017-04-03 12:56:35