发生WSAEWOULDBLOCK时如何判断链接是否断开

非阻塞socket,recv返回-1,WSAGetLastError返回WSAEWOULDBLOCK,无法判断对方是否宕机(因为网络繁忙的时候或者对方没有发送数据的时候也会返回WSAEWOULDBLOCK),此时需要使用其他方法来判断网络是否断开:
recv() will return 0 upon a graceful disconnect, ie the peer shutdown its end of the connection and its socket stack sent a FIN packet to your socket stack. You are pretty much guaranteed to get this result immediately, whether you use a blocking or non-blocking socket.

recv() will return -1 on any other error, including an abnormal connection loss. You need to use WSAGetLastError() to find out what actually happened. For a lost connection on a blocking socket, you will usually get an error code such as WSAECONNRESET or WSAECONNABORTED. For a lost connection on a non-blocking socket, it is possible that recv() may report an WSAEWOULDBLOCK error immediately and then report the actual error at some later time, maybe via select() with an exception fd_set, or an asynchronous notification, depending on how you implement your non-blocking logic.

However, either way, you are NOT guaranteed to get a failure result on a lost connection in any timely manner! It MAY take some time (seconds, minutes, can even be hours in rare cases) before the OS deems the connection is actually lost and invalidates the socket connection. TCP is designed to recover lost connections when possible, so it has to account for temporary network outages and such, so there are internal timeouts. You don’t see that in your code, it happens in the background.

If you don’t want to wait for the OS to timeout internally, you can always use your own timeout in your code, such as via select(), setsocktopt(SO_RCVTIMEO), TCP keep-alives (setsockopt(SO_KEEPALIVE) or WSAIoCtl(SIO_KEEPALIVE_VALS)), etc. You may still not get a failure immediately, but you will get it sooner rather than later.
参考网址:https://stackoverflow.com/questions/54787490/socket-recv-function
windows系统下,可使用如下方法判断:
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;
}
参考:https://blog.csdn.net/e_wsq/article/details/12878885

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值