TCP Keep-Alive

在tcp编程的过程中,我们发现在没有数据读写的静默的连接上,是没有办法发现tcp连接是有效的还是无效的。比如客户端突然崩溃,服务端可能几天都在维护一个无用的连接。

那么有没有办法开启类似的轮询机制,让tcp告诉我们,连接是不是还“活着”的呢?

这就是Tcp保持活跃机制所要解决的问题。实际上,TCP有一个保持活跃的机制叫做Keep-Alive.

这个机制的原理是:

定义一个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP保活机制会开始作用,每隔一个时间间隔,发送一个探测报文,该探测报文包含的数据非常少,如果连接几个探测报文都没有得到响应,则认为当前tcp连接已经死亡,系统内核将错误信息通知给上层应用程序。

上述的可定义变量,分别被称为保活时间,保活时间间隔和保活探测次数。在Linux系统中,这些变量分别对应sysctl变量里的

net.ipv4.tcp_keepalive_time,

net.ipv4.tcp_keepalive_intvl,

net.ipv4.tcp_keepalive_probes

默认设置是7200秒(2h),75s和9次探测。

如果开启了探活,需要考虑以下几种情况:

1.对端程序是正常的。当tcp的探测报文发送给对端,对端会正常响应,这样tcp保活时间会被重置,等待下一个tcp保活时间的到来。

2.对端程序崩溃,或对端由于其它原因导致报文不可达。当探测报文发送给对端后,石沉大海,没有响应,连续几次,达到保活探测次数后,tcp会报告该连接死亡。

tcp保活机制默认是关闭的,当我们选择打开时,可以分别在连接的两个方向上开启,也可以单独在一个方向上开启。如果开启服务器到客户端的检测,就可以在客户端非正常断连的情况下清楚服务端保留的脏数据;而开启客户端到服务器端的检测,就可以在服务器无响应的情况下,重新发起连接。

为什么tcp不提供一个频率很好的保活机制呢?

我的理解是早起的网络带宽非常有限,如果提供一个频率很高的机制,对有限的带宽是一个比较严重的浪费。

如果使用tcp自身的keep-alive机制,在Linux系统中,最少需要经过2h11m15s才可以发现一个死亡连接。这个时间是如何计算的?

静默状态下,2小时候开始探测,需要9次,每次间隔75s的时间 ,加起来就是这个时间。

这个时间现在看来是不可以接受的。所以我们可以在应用层自己设计一个保活机制。

发布了47 篇原创文章 · 获赞 39 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_28119741/article/details/104113970