关于检测SOCKET的异常断线

我的服务器代码中有类似的接收语句:

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异常!

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值