互聯(lián)網(wǎng)推送服務(wù)原理:長(zhǎng)連接+心跳機(jī)制(MQTT協(xié)議)
Android推送技術(shù)研究
Android實(shí)現(xiàn)推送方式解決方案
android設(shè)備休眠
Android微信智能心跳方案
微信收費(fèi)事件背后被廣泛忽略的技術(shù)細(xì)節(jié)
【Socket】關(guān)于socket長(zhǎng)連接的心跳包
一、概念
1.長(zhǎng)連接和短連接
短連接是通訊雙方有數(shù)據(jù)交互時(shí)就建立一個(gè)連接, 數(shù)據(jù)發(fā)送完成后,則斷開(kāi)此連接.長(zhǎng)連接就是大家建立連接之后, 不主動(dòng)斷開(kāi). 雙方互相發(fā)送數(shù)據(jù),發(fā)完了也不主動(dòng)斷開(kāi)連接,之后有需要發(fā)送的數(shù)據(jù)就繼續(xù)通過(guò)這個(gè)連接發(fā)送.
TCP連接在默認(rèn)的情況下就是所謂的長(zhǎng)連接, 也就是說(shuō)連接雙方都不主動(dòng)關(guān)閉連接, 這個(gè)連接就應(yīng)該一直存在.但是網(wǎng)絡(luò)中的情況是復(fù)雜的, 這個(gè)連接可能會(huì)被切斷. 比如客戶(hù)端到服務(wù)器的鏈路因?yàn)楣收蠑嗔? 或者服務(wù)器宕機(jī)了, 或者是你家網(wǎng)線(xiàn)被人剪了, 這些都是一些莫名其妙的導(dǎo)致連接被切斷的因素, 還有幾種比較特殊的:
(1)NAT超時(shí)
因?yàn)镮Pv4地址不足, 或者我們想通過(guò)無(wú)線(xiàn)路由器上網(wǎng), 我們的設(shè)備可能會(huì)處在一個(gè)NAT設(shè)備的后面, 生活中最常見(jiàn)的NAT設(shè)備是家用路由器.NAT設(shè)備會(huì)在IP封包通過(guò)設(shè)備時(shí)修改源/目的IP地址. 對(duì)于家用路由器來(lái)說(shuō), 使用的是網(wǎng)絡(luò)地址端口轉(zhuǎn)換(NAPT), 它不僅改IP, 還修改TCP和UDP協(xié)議的端口號(hào), 這樣就能讓內(nèi)網(wǎng)中的設(shè)備共用同一個(gè)外網(wǎng)IP. 舉個(gè)例子, NAPT維護(hù)一個(gè)類(lèi)似下表的NAT表
| 內(nèi)網(wǎng)地址 | 外網(wǎng)地址 |
|:-:|:-:|:-:|
| 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設(shè)備會(huì)根據(jù)NAT表對(duì)出去和進(jìn)來(lái)的數(shù)據(jù)做修改, 比如將192.168.0.3:8888發(fā)出去的封包改成120.132.92.21:9202, 外部就認(rèn)為他們是在和120.132.92.21:9202通信. 同時(shí)NAT設(shè)備會(huì)將120.132.92.21:9202收到的封包的IP和端口改成192.168.0.3:8888, 再發(fā)給內(nèi)網(wǎng)的主機(jī), 這樣內(nèi)部和外部就能雙向通信了, 但如果其中192.168.0.3:8888 == 120.132.92.21:9202這一映射因?yàn)槟承┰虮籒AT設(shè)備淘汰了, 那么外部設(shè)備就無(wú)法直接與192.168.0.3:8888通信了.
我們的設(shè)備經(jīng)常是處在NAT設(shè)備的后面, 比如在大學(xué)里的校園網(wǎng), 查一下自己分配到的IP, 其實(shí)是內(nèi)網(wǎng)IP, 表明我們?cè)贜AT設(shè)備后面, 如果我們?cè)趯嬍以俳觽€(gè)路由器, 那么我們發(fā)出的數(shù)據(jù)包會(huì)多經(jīng)過(guò)一次NAT.
當(dāng)一臺(tái)智能手機(jī)連上移動(dòng)網(wǎng)絡(luò)時(shí),其實(shí)并沒(méi)有真正連接上Internet,運(yùn)營(yíng)商分配給手機(jī)的IP其實(shí)是運(yùn)營(yíng)商的內(nèi)網(wǎng)IP,手機(jī)終端要連接上Internet還必須通過(guò)運(yùn)營(yíng)商的網(wǎng)關(guān)進(jìn)行IP地址的轉(zhuǎn)換,這個(gè)網(wǎng)關(guān)簡(jiǎn)稱(chēng)為NAT(NetWork Address Translation),簡(jiǎn)單來(lái)說(shuō)就是手機(jī)終端連接Internet其實(shí)就是移動(dòng)內(nèi)網(wǎng)IP,端口,外網(wǎng)IP之間相互映射。相當(dāng)于在手機(jī)終端在移動(dòng)無(wú)線(xiàn)網(wǎng)絡(luò)這堵墻上打個(gè)洞與外面的Internet相連。
GGSN(GateWay GPRS Support Note 網(wǎng)關(guān)GPRS支持節(jié)點(diǎn))模塊就實(shí)現(xiàn)了NAT功能,由于大部分的移動(dòng)無(wú)線(xiàn)網(wǎng)絡(luò)運(yùn)營(yíng)商為了減少網(wǎng)關(guān)NAT映射表的負(fù)荷,如果一個(gè)鏈路有一段時(shí)間沒(méi)有通信時(shí)就會(huì)刪除其對(duì)應(yīng)表,造成鏈路中斷,正是這種刻意縮短空閑連接的釋放超時(shí),原本是想節(jié)省信道資源的作用,沒(méi)想到讓互聯(lián)網(wǎng)的應(yīng)用不得以遠(yuǎn)高于正常頻率發(fā)送心跳來(lái)維護(hù)推送的長(zhǎng)連接。這也是為什么會(huì)有之前的信令風(fēng)暴,微信搖收費(fèi)的傳言,因?yàn)檫@類(lèi)的應(yīng)用發(fā)送心跳的頻率是很短的,既造成了信道資源的浪費(fèi),也造成了手機(jī)電量的快速消耗。參見(jiàn)微信收費(fèi)事件背后被廣泛忽略的技術(shù)細(xì)節(jié)
(2)網(wǎng)絡(luò)狀態(tài)切換
手機(jī)網(wǎng)絡(luò)和WIFI網(wǎng)絡(luò)切換, 網(wǎng)絡(luò)斷開(kāi)和連上等情況, 也會(huì)使長(zhǎng)連接斷開(kāi). 這里原因可能比較多, 但結(jié)果無(wú)非就是IP變了, 或者被系統(tǒng)通知連接斷了.
(3)DHCP的租期
目前測(cè)試發(fā)現(xiàn)安卓系統(tǒng)對(duì)DHCP的處理有Bug, DHCP租期到了不會(huì)主動(dòng)續(xù)約并且會(huì)繼續(xù)使用過(guò)期IP, 這個(gè)問(wèn)題會(huì)造成TCP長(zhǎng)連接偶然的斷連.
2.心跳機(jī)制
首先我們知道,維護(hù)任何一個(gè)長(zhǎng)連接都需要心跳機(jī)制,客戶(hù)端發(fā)送一個(gè)心跳給服務(wù)器,服務(wù)器給客戶(hù)端一個(gè)心跳應(yīng)答,這樣就形成客戶(hù)端服務(wù)器的一次完整的握手,這個(gè)握手是讓雙方都知道他們之間的連接是沒(méi)有斷開(kāi),客戶(hù)端是在線(xiàn)的。如果超過(guò)一個(gè)時(shí)間的閾值,客戶(hù)端沒(méi)有收到服務(wù)器的應(yīng)答,或者服務(wù)器沒(méi)有收到客戶(hù)端的心跳,那么對(duì)客戶(hù)端來(lái)說(shuō)則斷開(kāi)與服務(wù)器的連接重新建立一個(gè)連接,對(duì)服務(wù)器來(lái)說(shuō)只要斷開(kāi)這個(gè)連接即可。
為什么要有心跳包呢? 其實(shí)主要是為了防止上面提到的NAT超時(shí), 既然一些NAT設(shè)備判斷是否淘汰NAT映射的依據(jù)是一定時(shí)間沒(méi)有數(shù)據(jù), 那么客戶(hù)端就主動(dòng)發(fā)一個(gè)數(shù)據(jù).
當(dāng)然, 如果僅僅是為了防止NAT超時(shí), 可以讓服務(wù)器來(lái)發(fā)送心跳包給客戶(hù)端, 不過(guò)這樣做有個(gè)弊病就是, 萬(wàn)一連接斷了, 服務(wù)器就再也聯(lián)系不上客戶(hù)端了. 所以心跳包必須由客戶(hù)端發(fā)送, 客戶(hù)端發(fā)現(xiàn)連接斷了, 還可以嘗試重連服務(wù)器.
所以心跳包的主要作用是防止NAT超時(shí), 其次是探測(cè)連接是否斷開(kāi).
明確一點(diǎn), TCP長(zhǎng)連接本質(zhì)上不需要心跳包來(lái)維持, 大家可以試一試, 讓兩臺(tái)電腦連上同一個(gè)wifi, 然后讓其中一臺(tái)做服務(wù)器, 另一臺(tái)用一個(gè)普通的沒(méi)有設(shè)置KeepAlive的Socket連上服務(wù)器, 只要兩臺(tái)電腦別斷網(wǎng), 路由器也別斷電, DHCP正常續(xù)租, 就這么放著, 過(guò)幾個(gè)小時(shí)再用其中一臺(tái)電腦通過(guò)之前建立的TCP連接給另一臺(tái)發(fā)消息, 另一臺(tái)肯定能收到.
既然心跳包的主要作用是防止NAT超時(shí), 那么這個(gè)間隔就大有文章了.發(fā)送心跳包勢(shì)必要先喚醒設(shè)備, 然后才能發(fā)送, 如果喚醒設(shè)備過(guò)于頻繁, 或者直接導(dǎo)致設(shè)備無(wú)法休眠, 會(huì)大量消耗電量, 而且移動(dòng)網(wǎng)絡(luò)下進(jìn)行網(wǎng)絡(luò)通信, 比在wifi下耗電得多. 所以這個(gè)心跳包的時(shí)間間隔應(yīng)該盡量的長(zhǎng), 最理想的情況就是根本沒(méi)有NAT超時(shí), 比如剛才我說(shuō)的兩臺(tái)在同一個(gè)wifi下的電腦, 完全不需要心跳包. 這也就是網(wǎng)上常說(shuō)的長(zhǎng)連接, 慢心跳
現(xiàn)實(shí)是殘酷的, 根據(jù)網(wǎng)上的一些說(shuō)法, 中移動(dòng)2/3G下, NAT超時(shí)時(shí)間為5分鐘, 中國(guó)電信3G則大于28分鐘, 理想的情況下, 客戶(hù)端應(yīng)當(dāng)以略小于NAT超時(shí)時(shí)間的間隔來(lái)發(fā)送心跳包.wifi下, NAT超時(shí)時(shí)間都會(huì)比較長(zhǎng), 據(jù)說(shuō)寬帶的網(wǎng)關(guān)一般沒(méi)有空閑釋放機(jī)制, GCM有些時(shí)候在wifi下的心跳比在移動(dòng)網(wǎng)絡(luò)下的心跳要快, 可能是因?yàn)閣ifi下聯(lián)網(wǎng)通信耗費(fèi)的電量比移動(dòng)網(wǎng)絡(luò)下小.
關(guān)于如何讓心跳間隔逼近NAT超時(shí)的間隔, 同時(shí)自動(dòng)適應(yīng)NAT超時(shí)間隔的變化, 可以參看Android微信智能心跳方案
如果客戶(hù)端心跳間隔是固定的, 那么服務(wù)器在連接閑置超過(guò)這個(gè)時(shí)間還沒(méi)收到心跳時(shí), 可以認(rèn)為對(duì)方掉線(xiàn), 關(guān)閉連接. 如果客戶(hù)端心跳會(huì)動(dòng)態(tài)改變, 如上節(jié)提到的微信心跳方案, 應(yīng)當(dāng)設(shè)置一個(gè)最大值, 超過(guò)這個(gè)最大值才認(rèn)為對(duì)方掉線(xiàn). 還有一種情況就是服務(wù)器通過(guò)TCP連接主動(dòng)給客戶(hù)端發(fā)消息出現(xiàn)寫(xiě)超時(shí), 可以直接認(rèn)為對(duì)方掉線(xiàn).
心跳包和輪詢(xún)看起來(lái)類(lèi)似, 都是客戶(hù)端主動(dòng)聯(lián)系服務(wù)器, 但是區(qū)別很大.
- 輪詢(xún)是為了獲取數(shù)據(jù), 而心跳是為了?;頣CP連接.
- 輪詢(xún)得越頻繁, 獲取數(shù)據(jù)就越及時(shí), 心跳的頻繁與否和數(shù)據(jù)是否及時(shí)沒(méi)有直接關(guān)系
- 輪詢(xún)比心跳能耗更高, 因?yàn)橐淮屋喸?xún)需要經(jīng)過(guò)TCP三次握手, 四次揮手, 單次心跳不需要建立和拆除TCP連接.
以下參考【Socket】關(guān)于socket長(zhǎng)連接的心跳包
內(nèi)網(wǎng)機(jī)器如果不主動(dòng)向外發(fā)起連接,外網(wǎng)機(jī)沒(méi)法直連內(nèi)網(wǎng)的,這也是內(nèi)網(wǎng)機(jī)安全的原因之一,又因?yàn)槁酚善鲿?huì)把這個(gè)關(guān)系記錄下來(lái),但是過(guò)一段時(shí)間這個(gè)記錄可能會(huì)丟失 ,所有每一個(gè)客戶(hù)端每隔一定時(shí)間就會(huì)向服務(wù)器發(fā)送消息,以保證服務(wù)器可以隨時(shí)找到你,這東西被稱(chēng)為心跳包。
理論上說(shuō),這個(gè)連接是一直保持連接的,但是實(shí)際情況中,如果中間節(jié)點(diǎn)出現(xiàn)什么故障是難以知道的。更要命的是,有的節(jié)點(diǎn)(防火墻)會(huì)自動(dòng)把一定時(shí)間之內(nèi)沒(méi)有數(shù)據(jù)交互的連接給斷掉。在這個(gè)時(shí)候,就需要我們的心跳包了,用于維持長(zhǎng)連接,?;?。在獲知了斷線(xiàn)之后,服務(wù)器邏輯可能需要做一些事情,比如斷線(xiàn)后的數(shù)據(jù)清理,重新連接……當(dāng)然,這個(gè)自然是要由邏輯層根據(jù)需求去做了。總的來(lái)說(shuō),心跳包主要也就是用于長(zhǎng)連接的?;詈蛿嗑€(xiàn)處理。一般的應(yīng)用下,判定時(shí)間在30-40秒比較不錯(cuò)。如果實(shí)在要求高,那就在6-9秒。
如果不主動(dòng)關(guān)閉socket的話(huà),系統(tǒng)不會(huì)自動(dòng)關(guān)閉的,除非當(dāng)前進(jìn)程掛掉了,操作系統(tǒng)把占用的socket回收了才會(huì)關(guān)閉。為什么需要心跳連接主要是判斷當(dāng)前連接是否是有效的、可被使用的。在實(shí)際應(yīng)用中假設(shè)一段時(shí)間沒(méi)有數(shù)據(jù)傳輸時(shí)候理論上說(shuō)應(yīng)該連接是沒(méi)有問(wèn)題的,但是網(wǎng)絡(luò)復(fù)雜,中途出現(xiàn)問(wèn)題也是常見(jiàn)的,網(wǎng)線(xiàn)被掐斷了、對(duì)方進(jìn)程掛掉了、頻繁丟包等,這時(shí)候TCP連接是不可使用的,但是對(duì)于應(yīng)用層并不知道,如果需知道網(wǎng)絡(luò)情況則要很復(fù)雜的超時(shí)進(jìn)行了解,TCP從底層就實(shí)現(xiàn)了這樣的功能。心跳機(jī)制是TCP在一段時(shí)間間隔后發(fā)送確認(rèn)連接端是否還存在,如果存在的話(huà)就會(huì)回傳一個(gè)包確定網(wǎng)絡(luò)有效,如果心跳包有問(wèn)題,則通知上層應(yīng)用當(dāng)前網(wǎng)絡(luò)有問(wèn)題了。
這取決于你的server端的超時(shí)配置, 每個(gè)socket連接都是長(zhǎng)連接,它是一個(gè)相當(dāng)占用系統(tǒng)資源的通信管道, 如果這個(gè)長(zhǎng)連接什么事也沒(méi)干硬是要占著資源,則server端可以選擇關(guān)閉這個(gè)連接,以省下資源讓更多的用戶(hù)連接進(jìn)來(lái)。所以,即便客戶(hù)端的是采用死循環(huán)while(true)方式連到服務(wù)端,對(duì)于特定的客戶(hù)端和服務(wù)端類(lèi)型來(lái)說(shuō)也需要一定時(shí)間間隔的心跳(告訴服務(wù)端,我還活著,雖然我沒(méi)干活也沒(méi)說(shuō)話(huà),但別把我關(guān)了)
以前開(kāi)發(fā)手機(jī)游戲時(shí),索愛(ài)有一款手機(jī)有強(qiáng)制要求,客戶(hù)端如果超過(guò)三分鐘無(wú)消息發(fā)向網(wǎng)絡(luò)服務(wù)端,則會(huì)在客戶(hù)端自動(dòng)地強(qiáng)制把socket關(guān)斷。因?yàn)閟ocket長(zhǎng)連接相對(duì)于手機(jī)這樣資源少的設(shè)備來(lái)說(shuō)是寶貴的資源。 (這個(gè)強(qiáng)制是指客戶(hù)端系統(tǒng)自動(dòng)關(guān)的,不是我們代碼close的)
在TCP的機(jī)制里面,本身是存在有心跳包的機(jī)制的,也就是TCP的選項(xiàng):SO_KEEPALIVE。系統(tǒng)默認(rèn)是設(shè)置的2小時(shí)的心跳頻率。但是它檢查不到機(jī)器斷電、網(wǎng)線(xiàn)拔出、防火墻這些斷線(xiàn)。而且邏輯層處理斷線(xiàn)可能也不是那么好處理。一般,如果只是用于保活還是可以的。
心跳包一般來(lái)說(shuō)都是在邏輯層發(fā)送空的echo包來(lái)實(shí)現(xiàn)的。下一個(gè)定時(shí)器,在一定時(shí)間間隔下發(fā)送一個(gè)空包給客戶(hù)端,然后客戶(hù)端反饋一個(gè)同樣的空包回來(lái),服務(wù)器如果在一定時(shí)間內(nèi)收不到客戶(hù)端發(fā)送過(guò)來(lái)的反饋包,那就只有認(rèn)定說(shuō)掉線(xiàn)了。其實(shí),要判定掉線(xiàn),只需要send或者recv一下,如果結(jié)果為零,則為掉線(xiàn)。
3.android系統(tǒng)的推送和iOS的推送有什么區(qū)別
首先我們必須知道,所有的推送功能必須有一個(gè)客戶(hù)端和服務(wù)器的長(zhǎng)連接,因?yàn)橥扑褪怯煞?wù)器主動(dòng)向客戶(hù)端發(fā)送消息,如果客戶(hù)端和服務(wù)器之間不存在一個(gè)長(zhǎng)連接那么服務(wù)器是無(wú)法來(lái)主動(dòng)連接客戶(hù)端的。因而推送功能都是基于長(zhǎng)連接的基礎(chǔ)是上的。IOS長(zhǎng)連接是由系統(tǒng)來(lái)維護(hù)的,也就是說(shuō)蘋(píng)果的IOS系統(tǒng)在系統(tǒng)級(jí)別維護(hù)了一個(gè)客戶(hù)端和蘋(píng)果服務(wù)器的長(zhǎng)鏈接,IOS上的所有應(yīng)用上的推送都是先將消息推送到蘋(píng)果的服務(wù)器然后將蘋(píng)果服務(wù)器通過(guò)這個(gè)系統(tǒng)級(jí)別的長(zhǎng)鏈接推送到手機(jī)終端上,這樣的幾個(gè)好處為:
- 在手機(jī)終端始終只要維護(hù)一個(gè)長(zhǎng)連接即可,而且由于這個(gè)長(zhǎng)鏈接是系統(tǒng)級(jí)別的不會(huì)出現(xiàn)被殺死而無(wú)法推送的情況。
- 省電,不會(huì)出現(xiàn)每個(gè)應(yīng)用都各自維護(hù)一個(gè)自己的長(zhǎng)連接。
- 安全,只有在蘋(píng)果注冊(cè)的開(kāi)發(fā)者才能夠進(jìn)行推送,等等。
android的長(zhǎng)連接是由每個(gè)應(yīng)用各自維護(hù)的,但是google也推出了和蘋(píng)果技術(shù)架構(gòu)相似的推送框架,C2DM,云端推送功能,但是由于google的服務(wù)器不在中國(guó)境內(nèi),其他的原因你懂的。所以導(dǎo)致這個(gè)推送無(wú)法使用,android的開(kāi)發(fā)者不得不自己去維護(hù)一個(gè)長(zhǎng)鏈接,于是每個(gè)應(yīng)用如果都24小時(shí)在線(xiàn),那么都得各自維護(hù)一個(gè)長(zhǎng)連接,這種電量和流量的消耗是可想而知的。雖然國(guó)內(nèi)也出現(xiàn)了各種推送平臺(tái),但是都無(wú)法達(dá)到只維護(hù)一個(gè)長(zhǎng)連接這種消耗的級(jí)別。
4.AP BP 喚醒
首先Android手機(jī)有兩個(gè)處理器, 一個(gè)叫Application Processor(AP), 一個(gè)叫Baseband Processor(BP). AP是ARM架構(gòu)的處理器,用于運(yùn)行Android系統(tǒng); BP用于運(yùn)行實(shí)時(shí)操作系統(tǒng)(RTOS), 通訊協(xié)議棧運(yùn)行于BP的RTOS之上. 非通話(huà)時(shí)間, BP的能耗基本上在5mA左右,而AP只要處于非休眠狀態(tài), 能耗至少在50mA以上, 執(zhí)行圖形運(yùn)算時(shí)會(huì)更高. 另外LCD工作時(shí)功耗在100mA左右, WIFI也在100mA左右. 一般手機(jī)待機(jī)時(shí), AP, LCD, WIFI均進(jìn)入休眠狀態(tài), 這時(shí)Android中應(yīng)用程序的代碼也會(huì)停止執(zhí)行.
Android為了確保應(yīng)用程序中關(guān)鍵代碼的正確執(zhí)行, 提供了Wake Lock的API, 使得應(yīng)用程序有權(quán)限通過(guò)代碼阻止AP進(jìn)入休眠狀態(tài). 但如果不領(lǐng)會(huì)Android設(shè)計(jì)者的意圖而濫用Wake Lock API, 為了自身程序在后臺(tái)的正常工作而長(zhǎng)時(shí)間阻止AP進(jìn)入休眠狀態(tài), 就會(huì)成為待機(jī)電池殺手.
完全沒(méi)必要擔(dān)心AP休眠會(huì)導(dǎo)致收不到消息推送. 通訊協(xié)議棧運(yùn)行于BP,一旦收到數(shù)據(jù)包, BP會(huì)將AP喚醒, 喚醒的時(shí)間足夠AP執(zhí)行代碼完成對(duì)收到的數(shù)據(jù)包的處理過(guò)程. 其它的如Connectivity事件觸發(fā)時(shí)AP同樣會(huì)被喚醒. 那么唯一的問(wèn)題就是程序如何執(zhí)行向服務(wù)器發(fā)送心跳包的邏輯. 你顯然不能靠AP來(lái)做心跳計(jì)時(shí). Android提供的Alarm Manager就是來(lái)解決這個(gè)問(wèn)題的. Alarm應(yīng)該是BP計(jì)時(shí)(或其它某個(gè)帶石英鐘的芯片,不太確定,但絕對(duì)不是AP), 觸發(fā)時(shí)喚醒AP執(zhí)行程序代碼. 那么Wake Lock API有啥用呢? 比如心跳包從請(qǐng)求到應(yīng)答, 比如斷線(xiàn)重連重新登陸這些關(guān)鍵邏輯的執(zhí)行過(guò)程, 就需要Wake Lock來(lái)保護(hù). 而一旦一個(gè)關(guān)鍵邏輯執(zhí)行成功, 就應(yīng)該立即釋放掉Wake Lock了. 兩次心跳請(qǐng)求間隔5到10分鐘, 基本不會(huì)怎么耗電. 除非網(wǎng)絡(luò)不穩(wěn)定. 頻繁斷線(xiàn)重連, 那種情況辦法不多.
二、方式
要獲取服務(wù)器上不定時(shí)更新的信息,一般來(lái)說(shuō)有兩種方法:第一種是客戶(hù)端使用Pull(拉)的方式,就是隔一段時(shí)間就去服務(wù)器上獲取一下信息,看是否有更新的信息出現(xiàn)。第二種就是 服務(wù)器使用Push(推送)的方式,當(dāng)服務(wù)器端有新信息了,則把最新的信息Push到客戶(hù)端上。這樣,客戶(hù)端就能自動(dòng)的接收到消息。雖然Pull和Push兩種方式都能實(shí)現(xiàn)獲取服務(wù)器端更新信息的功能,但是明顯來(lái)說(shuō)Push方式比Pull方式更優(yōu)越。因?yàn)镻ull方式更費(fèi)客戶(hù)端的網(wǎng)絡(luò)流量,更主要的是費(fèi)電量,還需要我們的程序不停地去監(jiān)測(cè)服務(wù)端的變化。
1.輪詢(xún)(Pull)
客戶(hù)端定期詢(xún)問(wèn)服務(wù)器有沒(méi)有新的消息, 這樣服務(wù)器不用管客戶(hù)端的地址是什么, 客戶(hù)端來(lái)問(wèn), 直接告訴它就行.這種方案最簡(jiǎn)單, 對(duì)于一些不追求實(shí)時(shí)性的客戶(hù)端來(lái)說(shuō), 很適合, 只需要把時(shí)間間隔設(shè)定成幾個(gè)小時(shí)取一次, 就能很方便的解決問(wèn)題.但對(duì)于即時(shí)通訊產(chǎn)品來(lái)說(shuō), 這種方案完全不能用. 假設(shè)即時(shí)通訊軟件在網(wǎng)絡(luò)暢通的情況下發(fā)送的消息要求對(duì)方10s內(nèi)就能收到, 如果用輪詢(xún), 那么客戶(hù)端要每隔5s連一次服務(wù)器, 如果在移動(dòng)端, 手機(jī)的電量和流量很快就會(huì)被消耗殆盡.
2.SMS通知(Push)
這種方案在移動(dòng)端是有可能的, 讓客戶(hù)端攔截手機(jī)短信, 服務(wù)器在有新消息時(shí)給用戶(hù)的手機(jī)號(hào)發(fā)一條特殊的短信, 客戶(hù)端攔截短信后發(fā)現(xiàn)是正常短信就放行, 如果是特殊短信就連接服務(wù)器取消息.運(yùn)營(yíng)商不會(huì)配合, 用戶(hù)也不會(huì)放心, 這方案普通公司玩不起.
3.長(zhǎng)連接(Push)
這大概是目前情況下最佳的方案了, 客戶(hù)端主動(dòng)和服務(wù)器建立TCP長(zhǎng)連接之后, 客戶(hù)端定期向服務(wù)器發(fā)送心跳包, 有消息的時(shí)候, 服務(wù)器直接通過(guò)這個(gè)已經(jīng)建立好的TCP連接通知客戶(hù)端.
4.XMPP, MQTT協(xié)議
XMPP簡(jiǎn)介:
參考XMPP協(xié)議實(shí)現(xiàn)原理介紹
事實(shí)上Google官方的C2DM服務(wù)器底層也是采用XMPP協(xié)議進(jìn)行的封裝。XMPP(可擴(kuò)展通訊和表示協(xié)議)是基于可擴(kuò)展標(biāo)記語(yǔ)言(XML)的協(xié)議,它用于即時(shí)消息(IM)以及在線(xiàn)探測(cè)。
MQTT簡(jiǎn)介:
參考
MQTT 折騰筆記----協(xié)議簡(jiǎn)讀
MQTT協(xié)議(一):理論篇
以下部分,參考移動(dòng)端消息推送 xmpp 和 mqtt 哪個(gè)更費(fèi)電?
使用XMPP協(xié)議(Openfire + Spark + Smack)
簡(jiǎn)介:基于XML協(xié)議的通訊協(xié)議,前身是Jabber,目前已由IETF國(guó)際標(biāo)準(zhǔn)化組織完成了標(biāo)準(zhǔn)化工作。
優(yōu)點(diǎn):協(xié)議成熟、強(qiáng)大、可擴(kuò)展性強(qiáng)、目前主要應(yīng)用于許多聊天系統(tǒng)中,且已有開(kāi)源的Java版的開(kāi)發(fā)實(shí)例androidpn。
缺點(diǎn):協(xié)議較復(fù)雜、冗余(基于XML)、費(fèi)流量、費(fèi)電,部署硬件成本高。
使用MQTT協(xié)議
簡(jiǎn)介:輕量級(jí)的、基于代理的“發(fā)布/訂閱”模式的消息傳輸協(xié)議。
優(yōu)點(diǎn):協(xié)議簡(jiǎn)潔、小巧、可擴(kuò)展性強(qiáng)、省流量、省電,目前已經(jīng)應(yīng)用到企業(yè)領(lǐng)域,且已有C++版的服務(wù)端組件rsmb。
缺點(diǎn):不夠成熟、實(shí)現(xiàn)較復(fù)雜、服務(wù)端組件rsmb不開(kāi)源,部署硬件成本較高。
MQTT相比XMPP 有幾個(gè)優(yōu)勢(shì):二進(jìn)制,非常精簡(jiǎn),適合做大量節(jié)點(diǎn)弱網(wǎng)絡(luò)差的場(chǎng)景,非常適合現(xiàn)在移動(dòng)互聯(lián)網(wǎng)的基礎(chǔ)設(shè)施;MQTT是天然的訂閱發(fā)布系統(tǒng),有權(quán)限的人都可以往里頭發(fā)消息;開(kāi)源的協(xié)議和實(shí)現(xiàn);擴(kuò)展方便且輕量級(jí)。
XMPP不適合移動(dòng)網(wǎng)絡(luò)有幾個(gè)原因:協(xié)議雖然完整擴(kuò)展性雖然好,它耗費(fèi)網(wǎng)絡(luò)流量很大,交互次數(shù)太多,跑起來(lái)比MQTT慢很多;另外有高達(dá)70%的流量是耗費(fèi)在XMPP本身的標(biāo)簽和編解碼上面。
MQTT是一個(gè)由 IBM 開(kāi)發(fā)的傳輸協(xié)議,它被設(shè)計(jì)用于輕量級(jí)的發(fā)布/訂閱式消息傳輸,旨在為低帶寬和不穩(wěn)定的網(wǎng)絡(luò)環(huán)境中的設(shè)備提供可靠的網(wǎng)絡(luò)服務(wù)。相比于XMPP等傳統(tǒng)協(xié)議,MQTT 是專(zhuān)門(mén)針對(duì)移動(dòng)互聯(lián)網(wǎng)開(kāi)發(fā)的輕量級(jí)傳輸協(xié)議,這種傳輸協(xié)議連接穩(wěn)定、心跳數(shù)據(jù)包小,所以具備耗電量低、耗流量低的優(yōu)勢(shì)。推送服務(wù)的最佳協(xié)議!
5.第三方推送
在推送這一分支領(lǐng)域有許許多多的第三方推送服務(wù),例如:極光,個(gè)推等。
優(yōu)點(diǎn)是集成方便。
缺點(diǎn)是大量推送數(shù)據(jù)后,付費(fèi)服務(wù)是在所難免。
參考
目前國(guó)內(nèi)做消息推送的有云巴,百度,蝴蝶,極光,個(gè)推哪個(gè)比較好點(diǎn)
集成第三方推送最佳實(shí)踐