网络编程-keepalive

Posted 一周思进

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络编程-keepalive相关的知识,希望对你有一定的参考价值。

提到一方断网,通信两端是感知不到的,文章举例的客户端则是因为有在数据发送,在重传无果后关闭了连接。

但服务器只是单纯的接收数据,没有进行数据发送,所以它一直维护着这个无效的连接。如果客户端也不发送数据,那两边都一直维护着这个无效的连接。

那要怎么办可以去除这些无效的连接呢?可以通过TCP的keepalive机制来实现。

TCP的keepalive机制可以通过套接字选项SO_KEEPALIVE开启,在2小时内(默认值,可通过TCP_KEEPIDLE选项修改)该套接字上两端都无数据交换(如果中间有数据发送则重新开始计时),则设置的一方就会发送keep-alive探测包。

1、如果收到了对端的ack响应,则说明对端还在,继续保持该连接。(需要说明这只能表明该连接通信没问题,但不能表明对端一定还能正常收发数据处理,可能更多的还是通过上层应用来发送心跳包确认)

2、如果收到RST包,那说明对端已不在了,该套接字的待处理错误被设置为ECONNRESET。

3、如果没收到响应,则会尝试重发几次(由TCP_KEEPCNT选项控制),每次发送间隔由TCP_KEEPINTVL选项控制,如果最终都无响应,则也关闭该连接,待处理错误可能为ETIMEOUT或者EHOSTUNREACH。

因此关键几个配置操作如下:

 int keepalive = 1    // 开启keep-alive机制
int keepidle = 1800 // 无数据包交互到发送探测包的间隔时间,单位秒
int keepinterval = 3 // 开始探测后发送包的间隔时间,单位秒
int keepcount = 4 // 发送探测包数
setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive));
setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle));
setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &keepinterval, sizeof(keepinterval));
setsockopt(socket, IPPROTO_TCP, TCP_KEEPCNT, &keepcount, sizeof(keepcount));

需要注意上述配置都不能设置的过小了,否则可能一个正常的连接也关闭了,或者浪费不必要的带宽来发送这些检测包。

这个选项的使用场景通常是服务器进行设置,因为服务器会比较关注资源的及时释放。当然客户端也可以进行设置,比如发现服务器连接不上了,可以重新尝试连接。

不过两边的处理方式会不大一样,一般而言服务器都是阻塞等待读取操作,所以如果keepalive检测到对端不在了,则读操作返回,并得知相应的错误信息。

而客户端一般是主动发送,只是保持长连接,有数据时就发送下,并没有select等待读操作,可能就需要单独的检测线程来进行select读操作来判断是否连接断开了,并进行重连等操作。不过想想么,是不是还不如客户端直接尝试发送,如果发送失败了,那再重新建立连接好了。

另外需要注意的是,该错误信息需要通过SO_ERROR选项来获取,可以看

UNIX网络编程卷1中图7-6对于TCP连接检测做了汇总,如下图所示:



推荐阅读:






--End--


每周学习总结,相信可以走的更远。

以上是关于网络编程-keepalive的主要内容,如果未能解决你的问题,请参考以下文章

不为人知的网络编程:彻底搞懂TCP协议层的KeepAlive保活机制

网络编程-keepalive

网络编程之 keepalive(zz)

SO_KEEPALIVE 的 C 套接字编程

如何正确保障网络连接状态的通断--一文读懂keepalive的工作机制

我就是认真:正确保障网络连接状态的通断,一文读懂 Keepalive 工作机制