websocket心跳包的必要性

Posted by JC on March 24, 2020

心跳包

心跳的原因:虽然理论tcp连接后一直不断,但实际上会断网。见:比如 NAT超时,国内移动无线网络运营商在链路上一段时间内没有数据通讯后, 会淘汰NAT表中的对应项, 造成链路中断.

心跳包的主要作用是告知对方连接端,我还活着,心还在跳。

心跳时长多少?

现实是残酷的, 根据网上的一些说法, 中移动2/3G下, NAT超时时间为5分钟, 中国电信3G则大于28分钟, 理想的情况下, 客户端应当以略小于NAT超时时间的间隔来发送心跳包.

wifi下, NAT超时时间都会比较长, 据说宽带的网关一般没有空闲释放机制, GCM有些时候在wifi下的心跳比在移动网络下的心跳要快, 可能是因为wifi下联网通信耗费的电量比移动网络下小.

心跳包和轮询的区别

心跳包和轮询看起来类似, 都是客户端主动联系服务器, 但是区别很大.

  • 轮询是为了获取数据, 而心跳是为了保活TCP连接.
  • 轮询得越频繁, 获取数据就越及时, 心跳的频繁与否和数据是否及时没有直接关系
  • 轮询比心跳能耗更高, 因为一次轮询需要经过TCP三次握手, 四次挥手, 单次心跳不需要建立和拆除TCP连接.

总结

一方面为了 NAT 需要,另一方面是业务需求。

在中间网络断掉后( client 网络断了、链路上的某个路由器断了) TCP 链接两端是不会收到任何通知的,所以这个时候是根本不会触发 @kyuuseiryuu 所说的 onClose 事件的。这个时候就需要依靠心跳去监听,如果发现对方掉线后就触发类似 onClose 的事件(不管是 client 还是 server ),所以业务的心跳是必须的(当然也可以通过自定义 tcp 的 keepalive 来实现)。