Prayer

在一般中寻求卓越
posts - 1256, comments - 190, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

如何判断socket已经断开

Posted on 2009-04-14 16:22 Prayer 阅读(26910) 评论(5)  编辑 收藏 引用 所属分类: SOCKET
最近在做一个服务器端程序,C/S结构。功能方面比较简单就是client端与server端建立连接,然后发送消息给server。我在server端会使用专门的线程处理一条socket连接。这就涉及到一个问题,如果socket连接断开(异常,正常)后,我如何才能感知到?server端这边是绝对被动的,sever端不能主动断开连接。也没有连接链路维持包之类的。client端发送数据的时间也是不定的。在socket连接断开后, server要能够感知到并释放资源。
这个问题在思考测试,询问同事之后,找到了一个方法,可以做到这一点。
当使用 select()函数测试一个socket是否可读时,如果select()函数返回值为1,且使用recv()函数读取的数据长度为0 时,就说明该socket已经断开。
为了更好的判定socket是否断开,我判断当recv()返回值小于等于0时,socket连接断开。但是还需要判断 errno是否等于 EINTR 。如果errno == EINTR 则说明recv函数是由于程序接收到信号后返回的,socket连接还是正常的,不应close掉socket连接。

PS:对于堵塞socket的recv函数会在以下三种情况下返回:
(1)recv到数据时,会返回。
(2)在整个程序接收到信号时,返回-1。errno = EINTR。//在程序的起始阶段,屏蔽掉信号的除外。部分信号还是屏蔽不掉的。
(3)socket出现问题时,返回-1.具体错误码看 man recv()
(4)一定要看 man 说明,很详细,很有帮助。
这种方法经过长时间测试后,是有效的。所以写出来让大家参考一下,请大家发表意见。

Feedback

# re: 如何判断socket已经断开  回复  更多评论   

2009-04-14 22:26 by Sunshine Alike
我最近也要写一个这方面类似的程序,有空可以交流一下

# re: 如何判断socket已经断开  回复  更多评论   

2009-06-29 11:38 by czg
@Sunshine Alike
如果select返回的是0的话,那该怎么判断了

# re: 如何判断socket已经断开  回复  更多评论   

2010-01-18 09:54 by sue
我的方法不一样,我用getsockopt来判断,还是蛮准确的
int SocketConnected(int sock)
{
if(sock<=0)
return 0;
struct tcp_info info;
int len=sizeof(info);
getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len);
if((info.tcpi_state==TCP_ESTABLISHED))
{
//myprintf("socket connected\n");
return 1;
}
else
{
//myprintf("socket disconnected\n");
return 0;
}
}

# re: 如何判断socket已经断开[未登录]  回复  更多评论   

2010-03-01 15:26 by su
我是用sue的方法,但是观察日志觉得好像有不准确的情况。因为客户端在断开后十几秒后程序重连还是能够重新连上的(注:局域网环境)。我也有看到判断为断开后,重连也连不上的情况。这使我对他将信将疑。

# re: 如何判断socket已经断开  回复  更多评论   

2010-12-09 09:25 by happy
@su

socket(阻塞)没有数据可读时,select超时,不会去recv(),要怎么判断socket断开连接?

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理