tcp keepalive time,tcp keepalive单向还是双向
路上有朋友说服务器非正常死亡,客户端无法感知。我说可以用KEEPLIVE增加检测。正好网上有一篇文章写的很详细。
以下是到http://space.itpub.net/25259598/viewspace-684112.的转机
在正常的TCP连接上,当我们调用下面的Recv或Send并无限等待时:
ret=recv(s,buf[idx],nLeft,flags);
或者
ret=send(s,buf[idx],nLeft,flags);
如果TCP连接被对方正常关闭,也就是说对方正确调用了closesocket(s)或shutdown(s),那么上面的Recv或Send调用会立即返回一个错误。这是因为closesocket(s)或shutdown(s)有一个正常的关闭过程,会告诉对方“TCP连接已经关闭,你不再需要发送或接收消息了”。但如果突然拔掉网线,TCP连接两端的机器突然断电或重启,那么此时执行Recv或Send操作的一方会因为没有接到连接中断的通知而一直等待,也就是长时间卡死。这种情况的解决方案是在TCP编程中启动keepAlive机制。
struct TCP _ KEEPALIVE in KEEPALIVE={ 0 };
无符号长整型ulin len=sizeof(struct TCP _ KEEPALIVE);
struct TCP _ KEEPALIVE ut KEEPALIVE={ 0 };
无符号长整型ulOutLen=sizeof(struct TCP _ KEEPALIVE);
无符号长整型ulBytesReturn=0;
inkeepalive . onoff=1;
inkeepalive . keepaliveinterval=5000;//单位是毫秒
inkeepalive . keepalivetime=1000;//单位是毫秒
ret=WSAIoctl(s,SIO_KEEPALIVE_VALS,(LPVOID) inKeepAlive,ulInLen,
(LPVOID) outKeepAlive,ulOutLen,ulBytesReturn,NULL,NULL);
这里,keepalivetime指的是TCP连接打开时的探测频率。一旦探测包没有返回,将以keepaliveinterval的频率发送。几次重试后,如果没有返回探测包,则断定TCP连接已经断开,因此可以立即返回上述Recv或Send调用,不会无限卡死。
上图说明了上面的话。在该条被点亮之前,TCP处于平滑状态。KeepAlive以1000毫秒(keepalivetime的值)的频率发送探测数据包。当它发送到第32个探测包时,探测包没有返回,所以它以5000毫秒的频率发送(keepalivetime的值)。经过几次重传,探测包都没有返回,就断定这个TCP连接已经断开!
对于Win2K/XP/2003,您可以从以下注册表项中找到影响整个系统的所有连接的keepalive参数:
[HKEY _ LOCAL _ MACHINE SYSTEM current control set Services Tcpip Parameters]
" KeepAliveTime"=dword:006ddd00
" KeepAliveInterval "=dword:000003 E8
" MaxDataRetries"="5 "
2小时的空闲时间对实用程序来说太长了。所以我们需要手动开启Keepalive功能,设置合理的Keepalive参数。在XP和WIN2003系统上,可以为单个套接字设置,但在windows2000中,不能单独设置。如果设置了,会影响整个系统的所有插座。