(转)长连接为何要发送心跳包
最近面试的时候,被闻到关于Android IM 的问题,因为之前做过一个类似于微信的聊天软件,当时面试官问我,为啥后台需要发送心跳包,我说发送心跳包的作用是维持长链接,然后面试官问我,为啥长连接要发送心跳包的时候,我愣住了, 我也不知道为啥长链接需要发送心跳包
回来之后我查询资料后发现,Android的推送在后台维持的服务都会发送心跳包来维持长连接,当一台智能手机连上移动网络的时候,其实并没有链接上Internet,运营商分配给手机的IP其实只是一个内网的ip,手机端要连上Internet必须要通过运营商的网关进行IP转换,这个网关称为NAT(Network address translation) ,简单来说手机链接internt 就是链接移动运营商的内网Ip 端口,外网相互映射
GGSN(Gateway GPRS support Note ) 模块就实现了NAT功能,由于大部分移动网络运营商为了减少网关NAT映射表的负荷,当一个链路有一段时间没有通信时,就会删除对应表,造成链路中断,正事这种可以缩短空闲连接的释放超时,原本是想节省通道的资源,没想到让互联网的应用,不得不以远高于正常频率发送心跳,来维护推送的长连接,例如移动2.5G网络,大约五分钟的基带空闲,连接就会被释放掉
由于移动网络的特点,长连接的心跳周期并不能设置的太长,否则长连接会被释放掉,造成客户端频繁的重连与登录,同时也不能设置的太短,太短会加重服务器的负担。
内网机器如果不主动向外发起连接,外网机没法直接连内网,这也是内网机安全的原因之一,又因为路由器会把内网发起的连接记录起来,但是过一段时间可能会记录丢失,所以客户端每隔一段时间都会向服务器发送消息,以保证服务器随时可以找到你,这个东西称为心跳包
理论上来说,每一个连接都会保持连接的,但实际情况是,如果中间节点出现故障是难以知道的 ,更要命的是有的节点(防火墙)会自动把一定时间内没有数据交互的连接给断掉,在这个时候就需要我们的心跳包来维持一直跟服务器有数据交互,在获知断线以后,服务器逻辑可能需要做一些事情,比如断线之后的数据清理与重新连接,总之心跳是用来维持长连接的保活与断线处理。
如果不主动关闭Socket的话,系统是不会自动关闭的,除非当前的进程已经挂掉了,操作系统把占用的Socket回收了才会关闭,为什么需要心跳包来判断当前连接是否有效可被使用的。在实际操作中,假设一段时间没有数据传输,理论上长连接应该是存活的,但是网路复杂中途出现的问题也会比较常见,譬如网线被掐断,对象进程被杀掉,频繁丢包,对方这时候的TCP长连接是不可使用的,,但是对于应用层并不知道。如果需要知道当前的网络状况则需要很复杂的超时进行了解,TCP底层就实现了这样的功能,心跳机制是TCP在一段时间间隔后发送确定连接是否存在,如果确定存在的话,就会回传一个包来确定连接是存在的,如果没有返回包的话,则应该通知上层,网络出现了问题,需要进行连接失败的操作了
所以,即便客户端是采用死循环的方式连接到服务器,对于特定的服务端与客户端来说也需要一定时间间隔的心跳,告诉服务器我还活着,虽然我没干活,也没说话,但是别把我给关了。