菜鸟笔记
提升您的技术认知

判断非阻塞socket是否已经断开的几种方法-ag真人游戏

判断非阻塞socket是否已经断开的几种方法

 

注意要区分不同操作系统分别进行测试, 包括windows, linux和unix会各有不同

 

在windows下比较简单,可以使用fd_close事件判断socket是否已经断开

 

bool issocketclosed(socket clientsocket)
{
 bool ret = false;
 handle closeevent = wsacreateevent();
 wsaeventselect(clientsocket, closeevent, fd_close);

 dword dwret = waitforsingleobject(closeevent, 0);
 
 if(dwret == wsa_wait_event_0)
  ret = true;
 else if(dwret == wsa_wait_timeout)
  ret = false;

 wsacloseevent(closeevent);
 return ret;
}

 

 

在unix/linux下,非阻塞模式socket可以采用recv msg_peek的方式进行判断,其中msg_peek保证了仅仅进行状态判断,而不影响数据接收

对于主动关闭的socket, recv返回-1,而且errno被置为9(#define ebadf   9 /* bad file number */)

或104 (#define econnreset 104 /* connection reset by peer */)

对于被动关闭的socket,recv返回0,而且errno被置为11(#define ewouldblock eagain /* operation would block */)

 

对正常的socket, 如果有接收数据,则返回>0, 否则返回-1,而且errno被置为11(#define ewouldblock eagain /* operation would block */)

 

因此对于简单的状态判断(不过多考虑异常情况),
    recv返回>0,   正常
    返回-1,而且errno被置为11  正常
    其它情况    关闭

 

#include

bool issocketclosed(int clientsocket)
{
 char buff[32];
 int recvbytes = recv(clientsocket, buff, sizeof(buff), msg_peek);
 
 int sockerr = errno;
 
 //cout << "in close function, recv " << recvbytes << " bytes, err " << sockerr << endl;
 
 if( recvbytes > 0) //get data
  return false;
 
 if( (recvbytes == -1) && (sockerr == ewouldblock) ) //no receive data
  return false;
   
 return true;
}

 

此外,所有操作系统上还可以通过tcp_keeplive实行心跳检测

网站地图