判断非阻塞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实行心跳检测