消息推送,就是在互聯(lián)網(wǎng)上通過(guò)定期傳送用戶(hù)需要的信息來(lái)減少信息過(guò)載的一項(xiàng)新技術(shù)沟优。推送技術(shù)通過(guò)自動(dòng)傳送信息給用戶(hù)涕滋,來(lái)減少用于網(wǎng)絡(luò)上搜索的時(shí)間。它根據(jù)用戶(hù)的興趣來(lái)搜索挠阁、過(guò)濾信息宾肺,并將其定期推給用戶(hù),幫助用戶(hù)高效率地發(fā)掘有價(jià)值的信息侵俗。
一锨用、輪詢(xún)
1、短輪詢(xún)
http短輪詢(xún)是服務(wù)器收到請(qǐng)求不管是否有數(shù)據(jù)都直接響應(yīng) http 請(qǐng)求; 瀏覽器受到 http 響應(yīng)隔一段時(shí)間在發(fā)送同樣的 http 請(qǐng)求查詢(xún)是否有數(shù)據(jù);
http 短輪詢(xún)的局限是實(shí)時(shí)性低;
http 長(zhǎng)輪詢(xún)是服務(wù)器收到請(qǐng)求后如果有數(shù)據(jù), 立刻響應(yīng)請(qǐng)求; 如果沒(méi)有數(shù)據(jù)就會(huì) hold 一段時(shí)間, 這段時(shí)間內(nèi)如果有數(shù)據(jù)立刻響應(yīng)請(qǐng)求; 如果時(shí)間到了還沒(méi)有數(shù)據(jù), 則響應(yīng) http 請(qǐng)求;瀏覽器受到 http 響應(yīng)后立在發(fā)送一個(gè)同樣 http 請(qǐng)求查詢(xún)是否有數(shù)據(jù);
http 長(zhǎng)輪詢(xún)的局限:
瀏覽器端對(duì)統(tǒng)一服務(wù)器同時(shí) http 連接有最大限制, 最好同一用戶(hù)只存在一個(gè)長(zhǎng)輪詢(xún);
服務(wù)器端沒(méi)有數(shù)據(jù) hold 住連接時(shí)會(huì)造成浪費(fèi), 容易產(chǎn)生服務(wù)器瓶頸;
二增拥、長(zhǎng)連接
1、http長(zhǎng)連接
目前 http 協(xié)議普遍使用的是 1.1 版本, 之前有個(gè) 1.0 版本, 兩者之間的一個(gè)區(qū)別是 1.1 支持http 長(zhǎng)連接, 或者叫持久連接.1.0 不支持 http 長(zhǎng)連接, 每次一個(gè) http 請(qǐng)求響應(yīng)后都關(guān)閉 tcp 連接, 下個(gè) http 請(qǐng)求會(huì)重新建立 tcp 連接.
所謂 http 長(zhǎng)連接, 就是多個(gè) http 請(qǐng)求共用一個(gè) tcp 連接; 這樣可以減少多次臨近 http 請(qǐng)求導(dǎo)致 tcp 建立關(guān)閉所產(chǎn)生的時(shí)間消耗. http 1.1 中在請(qǐng)求頭和相應(yīng)頭中用 connection字段標(biāo)識(shí)是否是 http 長(zhǎng)連接,connection: keep-alive, 表明是 http 長(zhǎng)連接;connection:closed, 表明服務(wù)器關(guān)閉 tcp 連接
與 connection 對(duì)應(yīng)的一個(gè)字段是keep-live, http 響應(yīng)頭中出現(xiàn), 他的格式是 timeout=30, max=5, timeout 是兩次 http 請(qǐng)求保持的時(shí)間(s), , max 是這個(gè) tcp 連接最多為幾個(gè) http 請(qǐng)求重用寻歧。
2掌栅、tcp長(zhǎng)連接
先說(shuō)短連接, 短連接是通訊雙方有數(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)該一直存在。
當(dāng)網(wǎng)絡(luò)通信時(shí)采用TCP協(xié)議時(shí)噪珊,在真正的讀寫(xiě)操作之前晌缘,server與client之間必須建立一個(gè)連接,
當(dāng)讀寫(xiě)操作完成后痢站,雙方不再需要這個(gè)連接時(shí)它們可以釋放這個(gè)連接磷箕,
連接的建立是需要三次握手的,而釋放則需要4次握手阵难,
所以說(shuō)每個(gè)連接的建立都是需要資源消耗和時(shí)間消耗的
經(jīng)典的三次握手示意圖:
經(jīng)典的四次握手關(guān)閉圖:
推送機(jī)制:
如何獲取新數(shù)據(jù)呢:
服務(wù)器端通知岳枷,客戶(hù)端獲取
客戶(hù)端攜帶最新的SyncKey,發(fā)起數(shù)據(jù)請(qǐng)求
服務(wù)器端生成最新的SyncKey連同最新數(shù)據(jù)發(fā)送給客戶(hù)端
基于版本號(hào)機(jī)制同步協(xié)議,可確保數(shù)據(jù)增量嫩舟、有序傳輸
SyncKey氢烘,由服務(wù)器端序列號(hào)生成器生成,一旦有新消息產(chǎn)生家厌,將會(huì)產(chǎn)生最新的SyncKey。類(lèi)似于版本號(hào)
服務(wù)器端通知有狀態(tài)更新椎工,客戶(hù)端主動(dòng)獲取自從上次更新之后有變動(dòng)的狀態(tài)數(shù)據(jù)饭于,增量式,順序式维蒙。
http://www.blogjava.net/yongboy/archive/2014/03/05/410636.html
心跳包标溃活
因?yàn)槭情L(zhǎng)連接, 所以需要定期發(fā)送心跳包;心跳包是用來(lái)通知服務(wù)器客戶(hù)端當(dāng)前狀態(tà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(動(dòng)態(tài)主機(jī)配置協(xié)議)正常續(xù)租, 就這么放著, 過(guò)幾個(gè)小時(shí)再用其中一臺(tái)電腦通過(guò)之前建立的TCP連接給另一臺(tái)發(fā)消息, 另一臺(tái)肯定能收到殖熟。
那為什么要有心跳包呢?
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表:
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.
國(guó)內(nèi)移動(dòng)無(wú)線(xiàn)網(wǎng)絡(luò)運(yùn)營(yíng)商在鏈路上一段時(shí)間內(nèi)沒(méi)有數(shù)據(jù)通訊后, 會(huì)淘汰NAT表中的對(duì)應(yīng)項(xiàng), 造成鏈路中斷斑响。
網(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)通知連接斷了.
DHCP(動(dòng)態(tài)主機(jī)配置協(xié)議)的租期
目前測(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)連接偶然的斷連菱属。
其實(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)纽门。
心跳包的時(shí)間間隔
既然心跳包的主要作用是防止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)連接, 慢心跳营罢。
根據(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ò)下小。
守護(hù)服務(wù)
1饲漾、系統(tǒng)鬧鈴服務(wù)定時(shí)發(fā)廣播檢查蝙搔;
2、監(jiān)聽(tīng)網(wǎng)絡(luò)變化考传、屏幕喚醒吃型;