Android推送技術研究
作者:網絡轉載 發布時間:[ 2016/3/11 11:33:00 ] 推薦標簽:移動開發
前言
近研究Android推送的實現, 研究了兩天一夜, 有了一點收獲, 寫下來既為了分享, 也為了吐槽. 需要說明的是有些東西偏底層硬件和通信行業, 我對這些一竅不通, 只能說說自己的理解.
為什么要研究Android推送技術? 主要還是畢業設計要做一個即時通信app, 我是不喜歡做什么社交app的, 也象牙塔里的人想得出來, 說實話有這功夫還不如鉆研一個小技術點, 把一個點研究透徹, 比搞個大而全, 還無用的東西好得多, 不過誰叫咱們是普通人, 沒得選呢.
Android推送服務的幾種實現方式
現實生活中, 推送服務像訂雜志一樣, 只要留下你的地址, 雜志能如期送到你手里, 可以認為每個人都有的一個地址, 但在目前的網絡上, 這是辦不到的, 因為不是每個人都有一個的地址, 服務器想要給我們推送一條消息, 必須知道我們的地址, 但服務器不知道我們在哪.
說到推送服務, 我所知道的實現方案有如下幾種:
輪詢
客戶端定期詢問服務器有沒有新的消息, 這樣服務器不用管客戶端的地址是什么, 客戶端來問, 直接告訴它行.
這種方案簡單, 對于一些不追求實時性的客戶端來說, 很適合, 只需要把時間間隔設定成幾個小時取一次, 能很方便的解決問題.
但對于即時通訊產品來說, 這種方案完全不能用. 假設即時通訊軟件在網絡暢通的情況下發送的消息要求對方10s內能收到, 如果用輪詢, 那么客戶端要每隔5s連一次服務器, 如果在移動端, 手機的電量和流量很快會被消耗殆盡.
SMS通知
這種方案在移動端是有可能的, 讓客戶端攔截手機短信, 服務器在有新消息時給用戶的手機號發一條特殊的短信, 客戶端攔截短信后發現是正常短信放行, 如果是特殊短信連接服務器取消息.
運營商不會配合, 用戶也不會放心, 這方案普通公司玩不起.
長連接
這大概是目前情況下佳的方案了, 客戶端主動和服務器建立TCP長連接之后, 客戶端定期向服務器發送心跳包, 有消息的時候, 服務器直接通過這個已經建立好的TCP連接通知客戶端.
XMPP, MQTT等不算推送技術
在網上搜索資料的時候, 經?匆奨MPP協議實現的Android推送和MQTT協議實現的Android推送, 我個人覺得這兩種說法都怪怪的, XMPP和MQTT二者都是協議, 盡管我不清楚嚴格來講這倆協議工作在哪一層, 但是是在傳輸層之上的, 姑且認為他倆在TCP/IP五層模型的應用層吧, 閉口不提傳輸層的實現, 而是扯應用層, 這種說法真是令我費解, 所以我個人認為XMPP, MQTT等等不算推送技術.
關于這個XMPP, 我想很多人都是參考Openfire和Smack那套東西, 我一年前嘗試用aSmack和Openfire做IM, 不過那個時候什么都不懂, 做的東西很爛, 懂的是Openfire這東西相當老了, 我看有一些開源的推送解決方案都是在這套東西的基礎上改的, 想想這工作量, 挺可怕的.
細說TCP長連接與心跳
長連接方案乍一聽怪怪的, 什么是長連接? 定時發送心跳, 這和輪詢有什么區別? 心跳是干什么的? 同樣是定期和服務器溝通, 為什么長連接比輪詢更加? 手機休眠了TCP連接不會斷掉嗎?
這是我在剛開始研究推送技術的時候的問題, 雖然有些還是沒有很準確的答案, 但了解的大概可以分享一下, 有什么錯誤歡迎指出.
什么是長連接
先說短連接, 短連接是通訊雙方有數據交互時建立一個連接, 數據發送完成后,則斷開此連接.
persistent connection
長連接是大家建立連接之后, 不主動斷開. 雙方互相發送數據, 發完了也不主動斷開連接, 之后有需要發送的數據繼續通過這個連接發送.
TCP連接在默認的情況下是所謂的長連接, 也是說連接雙方都不主動關閉連接, 這個連接應該一直存在.
但是網絡中的情況是復雜的, 這個連接可能會被切斷. 比如客戶端到服務器的鏈路因為故障斷了, 或者服務器宕機了, 或者是你家網線被人剪了, 這些都是一些莫名其妙的導致連接被切斷的因素, 還有幾種比較特殊的:
NAT超時
因為IPv4地址不足, 或者我們想通過無線路由器上網, 我們的設備可能會處在一個NAT設備的后面, 生活中常見的NAT設備是家用路由器.
NAT設備會在IP封包通過設備時修改源/目的IP地址. 對于家用路由器來說, 使用的是網絡地址端口轉換(NAPT), 它不僅改IP, 還修改TCP和UDP協議的端口號, 這樣能讓內網中的設備共用同一個外網IP. 舉個例子, NAPT維護一個類似下表的NAT表
內網地址 外網地址
192.168.0.2:5566 120.132.92.21:9200
192.168.0.3:7788 120.132.92.21:9201
192.168.0.3:8888 120.132.92.21:9202
NAT設備會根據NAT表對出去和進來的數據做修改, 比如將192.168.0.3:8888發出去的封包改成120.132.92.21:9202, 外部認為他們是在和120.132.92.21:9202通信. 同時NAT設備會將120.132.92.21:9202收到的封包的IP和端口改成192.168.0.3:8888, 再發給內網的主機, 這樣內部和外部能雙向通信了, 但如果其中192.168.0.3:8888 == 120.132.92.21:9202這一映射因為某些原因被NAT設備淘汰了, 那么外部設備無法直接與192.168.0.3:8888通信了.
我們的設備經常是處在NAT設備的后面, 比如在大學里的校園網, 查一下自己分配到的IP, 其實是內網IP, 表明我們在NAT設備后面, 如果我們在寢室再接個路由器, 那么我們發出的數據包會多經過一次NAT.
國內移動無線網絡運營商在鏈路上一段時間內沒有數據通訊后, 會淘汰NAT表中的對應項, 造成鏈路中斷.
網絡狀態切換
手機網絡和WIFI網絡切換, 網絡斷開和連上等情況, 也會使長連接斷開. 這里原因可能比較多, 但結果無非是IP變了, 或者被系統通知連接斷了.
DHCP的租期
目前測試發現安卓系統對DHCP的處理有Bug, DHCP租期到了不會主動續約并且會繼續使用過期IP, 這個問題會造成TCP長連接偶然的斷連.
引自Android微信智能心跳方案
心跳包的作用
網上很多文章介紹長連接的時候都說:
因為是長連接, 所以需要定期發送心跳包.
心跳包是用來通知服務器客戶端當前狀態.
提出這些說法的人其實自己也是一知半解. 這些說法其實都對, 但是沒有答到點上. 好像別人問: “你為什么要去食堂”? 這人回答: “檢查自己還能不能找到食堂”. 這個答案說不上錯了, 但是其實這人是去食堂吃飯的, 證明自己認得路只是個附贈品.
明確一點, TCP長連接本質上不需要心跳包來維持, 大家可以試一試, 讓兩臺電腦連上同一個wifi, 然后讓其中一臺做服務器, 另一臺用一個普通的沒有設置KeepAlive的Socket連上服務器, 只要兩臺電腦別斷網, 路由器也別斷電, DHCP正常續租, 這么放著, 過幾個小時再用其中一臺電腦通過之前建立的TCP連接給另一臺發消息, 另一臺肯定能收到.
相關推薦

最新發布
性能測試之測試環境搭建的方法
2020/7/21 15:39:32軟件測試是從什么時候開始被企業所重視的呢?
2020/7/17 9:09:11Android自動化測試框架有哪些?有什么用途?
2020/7/17 9:03:50什么樣的項目適合做自動化?自動化測試人員應具備怎樣的能力?
2020/7/17 8:57:06幾大市面主流性能測試工具測評
2020/7/17 8:52:11RPA機器人能夠快速響應企業需求,是怎么做到的?
2020/7/17 8:48:05Bug可以真正消滅嗎?為什么?
2020/7/17 8:43:03軟件測試基本概念是怎么來的?軟件測試生命周期的形成歷經了什么?
2020/7/16 9:11:10