Posted by & filed under Uncategorized.

About chenjin

JIn Chen has written 76 post in this blog.

KeepAlive使用

如果TCP连接被对方正常关闭,也就是说,对方是正确地调用了closesocket(s)或者shutdown(s)的话,那么recv或send调用就能马上返回,并且报错。这是由于closesocket()或者shutdown()有个正常的关闭过程,会告诉对方“TCP连接已经关闭,你不需要再发送或者接受消息了”。但是,如果是网线突然被拔掉,TCP连接的任何一端的机器突然断电或重启动,那么这时候正在执行recv或send操作的一方就会因为没有任何连接中断的通知而一直等待下去,也就是会被长时间卡住。这种情形解决的办法是启动TCP编程里的keepAlive机制。
keepalive作用:检测连接是否正常
在维护检测TCP的正常连接方面 SOL_SOCKET类提供了SO_KEEPALIVE 保持连接 int SO_RCVTIMEO 接收超时 struct timeval SO_SNDTIMEO 发送超时 struct timeval SOL_TCP类提供了TCP_KEEPIDLE。
在Linux系统下,如果对于TCP的socket启用了Keepalive选项,则会在7200秒(即两个小时)没有数据后,发起 KEEPALIVE报文。如果没有回应,则会在75秒后再次重试。如果重试9次均失败,则认定连接已经失效。在程序中表现为,当tcp检测到对端socket不再可用时(不能发出探测包,或探测包没有收到ACK的响应包),select会返回socket可读,并且在recv时返回-1,同时置上errno为ETIMEDOUT。
对于大多数应用来说,这两个时间值都有点太长了,我们可以在程序中自行定义和keepaliv相关值的大小以适合各自的程序运行环境,如:
int keepAlive = 1; // 开启keepalive属性
int keepIdle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测
int keepInterval = 5; // 探测时发包的时间间隔为5 秒
int keepCount = 3; // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发.

 

网线拔掉后,如果该socket一直在尝试接收,且不发送数据,则10秒左右能够收到断开信号。
但是如果socket一直在发送数据,则keepalive不起作用,
此时我们可以运用:

1.心跳包机制;

2.通过在connect之前设置SO_SNDTIMO来达到控制连接超时的目的,设置该属性后,当send函数将发送缓冲区填满时,在经过设置的时间以后,程序退出;

3. 删除Arp地址,通过检测是否能够再次获得对端mac地址来判断对方是否存活。缺点是不能跨越路由器,同样不能检测可以保证测试到对端的程序是否正常工作

Leave a Reply

  • (will not be published)