参考: 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连接.