TCP自带心跳keepalive

来源:互联网 发布:通话数据统计软件 编辑:程序博客网 时间:2024/06/07 10:02

今天去hj面试,面试官问了一个网络方面的问题,TCP有心跳包功能,为什么我们一般在写程序时还要在应用层加心跳功能? 

以前我写的通信程序,都在应用层加了心跳功能,虽然TCP是可靠传输,某一端断开连接的话,是会通知到另一端的,但对于断电、拔网线、路由器故障这种突发情况,就无法通知到网络上的另一端了,所以需要心跳功能隔一段时间来帮我们检测当前连接是否可用。

之前接触别人和自己写的代码都在应用层实现了心跳功能,就一直以为传输层本身是没有心跳功能的,所以还跟面试官争了半天传输层是没有心跳功能的,回来查了下资料,原来TCP是有KeeAlive机制的,想想真是太丢人了。

在TCP协议里,本身的心跳包机制SO_KEEPALIVE,系统默认设置的是7200秒的启动时间。默认是关闭的,需要用setsocketopt将SOL_SOCKET.SO_KEEPALIVE设置为1打开,有三个参数可以设置,tcp_keepalive_time、tcp_keepalive_probes、tcp_keepalive_intvl,分别表示连接闲置多久才开始发心跳包、连发几次心跳包没有回应表示连接已断开、心跳包之间间隔时间。

这里有一篇非常详细介绍TCP Keepalive的文章: http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO,2.2节提到

Why use TCPkeepalive?

1.Checking for dead peers(断线检测)

2.Preventing disconnection due to network inactivity(保活)

心跳包的作用:

1.保活

在传输的链路上,有的节点(防火墙、NAT)会自动把一定时间内没有数据交互的连接给断掉,这个时候就需要我们定时发送心跳包,让这些节点知道这条连接仍在使用中,维持长连接,保活。

2.断线处理

通过心跳包获知连接断开后,启动相应的处理机制,如重新连接、断线后的数据清理等。

对之前面试官提的问题:“既然TCP已有心跳机制,为什么我们还要在应用层实现自己的心跳功能呢?”,现在我想有这么几点理由:

1.TCP心跳机制是传输层实现的,只要当前连接是可用的,对端就会ACK我们的心跳,而对于当前对端应用是否能正常提供服务,TCP层的心跳机制是无法获知的。我们在应用层实现的心跳功能是依赖于对端应用的,如果对端当前无法正常提供服务,通过应用层心跳功能马上就可以获知,我们可以进行相应的处理;

2.tcp_keepalive_time参数的设置是秒级,对于极端情况,我们可能想在毫秒级就检测到连接的状态,这个TCP心跳机制就无法办到;

3.通用性,应用层心跳功能不依赖于传输层协议,如果有一天我们想将传输层协议由TCP改为UDP,那么传输层不提供心跳机制了,应用层的心跳是通用的,此时或许只用修改少量地方代码即可;

4.有些运营商会过滤掉keep包;

应用层心跳包不好的地方

增加开发工作量,由于应用特定的网络框架,还可能增加代码结构的复杂度,再就是根据上面的推测,应用层心跳的流量消耗还是更大的,毕竟这本质上还是个普通的数据包。

阅读全文
0 0