您的位置:首页 > 其它

关于检测SOCKET的异常断线

2010-01-30 15:45 253 查看
我的服务器代码中有类似的接收语句:

do {

FD_ZERO(&read_fds);

FD_SET((unsigned int)sock, &read_fds);

FD_ZERO(&write_fds);

if (out_queue)

FD_SET((unsigned int)sock, &write_fds);

tm.tv_sec = 0;

tm.tv_usec = 50;

count = select(sock + 1, &read_fds, &write_fds, NULL, &tm);

} while (count == 0);

if (FD_ISSET((unsigned int)sock, &read_fds)) {

// Try to read some data in

bytes = Read(buff, currlen);

...

}

1)当客户端以PC形式登录时,断开客户端的网线,能够跳出select的循环,并在read中判断出错误,并得到socket断线信息

2)当客户端以手机形式登录时(使用wifi),断开客户端的wifi连接,则始终不能跳出select循环,至少测试过等待5分钟后仍不能跳出,count始终为0.

于是从网上搜索的相关的讨论话题,发现这确实是一个很普遍的问题,很多的描述与此类似。一个基本的思路是靠在send中发送数据来检测断线,但在我的应用中没有心跳包,不便使用send判断。

为此找到了一篇官方文档,在http://support.microsoft.com/kb/140325,感觉到必须使用KEEPALIVE来尝试,为此加入了相关的代码进行实验,很幸运,实验成功!

需要加入的代码是:

#ifdef __WIN32__

tcp_keepalive inKeepAlive = {0};

unsigned long ulInLen = sizeof(tcp_keepalive);

tcp_keepalive outKeepAlive = {0};

unsigned long ulOutLen = sizeof(tcp_keepalive);

unsigned long ulBytesReturn = 0;

inKeepAlive.onoff = 1;

inKeepAlive.keepaliveinterval = 1000;

inKeepAlive.keepalivetime = 60000;

if (SOCKET_ERROR == WSAIoctl(sock, SIO_KEEPALIVE_VALS,

(LPVOID)&inKeepAlive, ulInLen,

(LPVOID)&outKeepAlive, ulOutLen,

&ulBytesReturn, NULL, NULL))

{

}

#endif

此后,当手机侧的WIFI手动关闭或按下电源键黑屏后,确实约1分钟后,select函数返回并在read中得到WSAECONNRESET异常!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: