參考: http://www.jianshu.com/p/584707554ed7
TCP連接配接建立後隻要不明确關閉,邏輯上連接配接一直存在。
TCP是有保活定時器的,可以打開保活定時器來維持長連接配接,設定SO_KEEPALIVE才會開啟,時間間隔預設7200s,也就是2h,這個預設是關閉的。
注意:HTTP的keepalive和TCP的用處不大一樣tcp。
因為 IP v4 的 IP 量有限,營運商配置設定給手機終端的 IP 是營運商内網的 IP,手機要連接配接 Internet,就需要通過營運商的網關做一個網絡位址轉換(Network Address Translation,NAT)。簡單的說營運商的網關需要維護一個外網 IP、端口到内網 IP、端口的對應關系,以確定内網的手機可以跟 Internet 的伺服器通訊。
大部分移動無線網絡營運商都在鍊路一段時間沒有資料通訊時,會淘汰 NAT 表中的對應項,造成鍊路中斷。
長連接配接心跳間隔必須要小于NAT逾時時間(aging-time),如果超過aging-time不做心跳,TCP長連接配接鍊路就會中斷,Server就無法發送Push給手機,隻能等到用戶端下次心跳失敗後,重建連接配接才能取到消息。
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表對出去和進來的資料做修改, 比如将<code>192.168.0.3:8888</code>發出去的封包改成<code>120.132.92.21:9202</code>, 外部就認為他們是在和<code>120.132.92.21:9202</code>通信. 同時NAT裝置會将<code>120.132.92.21:9202</code>收到的封包的IP和端口改成<code>192.168.0.3:8888</code>, 再發給内網的主機, 這樣内部和外部就能雙向通信了, 但如果其中<code>192.168.0.3:8888 == 120.132.92.21:9202</code>這一映射因為某些原因被NAT裝置淘汰了, 那麼外部裝置就無法直接與<code>192.168.0.3:8888</code>通信了.
國内移動無線網絡營運商在鍊路上一段時間内沒有資料通訊後, 會淘汰NAT表中的對應項, 造成鍊路中斷.
心跳的原因:雖然理論tcp連接配接後一直不斷,但實際上會斷網。見:比如 NAT逾時,更多 影響TCP連接配接壽命的因素
心跳包的主要作用是告知對方連接配接端,我還活着,心還在跳。
心跳時長多少?
現實是殘酷的, 根據網上的一些說法, 中移動2/3G下, NAT逾時時間為5分鐘, 中國電信3G則大于28分鐘, 理想的情況下, 用戶端應當以略小于NAT逾時時間的間隔來發送心跳包.
地區/網絡
NAT逾時時間
中國移動3G和2G
5分鐘
中國聯通2G
中國電信3G
大于28分鐘
美國3G
台灣3G
wifi下, NAT逾時時間都會比較長, 據說寬帶的網關一般沒有空閑釋放機制, GCM有些時候在wifi下的心跳比在移動網絡下的心跳要快, 可能是因為wifi下聯網通信耗費的電量比移動網絡下小.
心跳包和輪詢看起來類似, 都是用戶端主動聯系伺服器, 但是差別很大.
輪詢是為了擷取資料, 而心跳是為了保活TCP連接配接.
輪詢得越頻繁, 擷取資料就越及時, 心跳的頻繁與否和資料是否及時沒有直接關系
輪詢比心跳能耗更高, 因為一次輪詢需要經過TCP三向交握, 四次揮手, 單次心跳不需要建立和拆除TCP連接配接.