如何检查客户端是否通过C ++中的Winsock断开连接?
答案 0 :(得分:12)
Beej's Network Programming Guide
如果在阻塞模式下调用recv并返回0字节读取,则套接字已断开连接,否则等待接收字节。
查看此FAQ 2.12
示例来自this页面上的选择。
int nRet;
if(( nRet = select( 0, &fdread, NULL, NULL, NULL )) == SOCKET_ERROR )
{
// Error condition
// Check WSAGetLastError
}
if( nRet > 0 )
{
// select() will return value 1 because i m using only one socket
// At this point, it should be checked whether the
// socket is part of a set.
if( FD_ISSET( s, &fdread ))
{
// A read event has occurred on socket s
}
}
答案 1 :(得分:5)
您只能通过尝试发送数据来判断TCP套接字是否“已断开连接”。这是因为协议的设计应该允许在对等体之间暂时中断。因此,如果您从A通过R1经过R2连接到B并发送数据一段时间然后停止发送,您可以拔掉R2-> R3(例如),A和B都不会注意到(或关注)。如果你然后插入了R2-> R4和R4-> R3然后尝试在A和B之间发送数据,那么事情就会“正常工作”而你永远不会知道。但是,如果您在R2-> R3断开连接时尝试发送数据,那么您(最终在所有TCP级别重试之后)会收到错误。
现在,某些操作系统可能会提醒您当前网络适配器当前未连接的事实,您可以使用它来说“我不再与同行连接”,但我不会建议。
如果让你的同伴知道什么时候连接被“破坏”很重要,那么要么使用应用程序级别的“ping”消息偶尔在对等体之间发送数据,要么使用TCP keep-alive。就个人而言,我会选择ping消息......
编辑当然所有这一切都假设您想知道您是否仍然可以在连接上发送数据,毕竟,当客户端不再发送因为您的读取时您已经被告知将返回0字节,你知道何时断开它的发送端,因为你的写入将失败;你也知道什么时候关闭你自己的连接端的发送或接收端......
我想我应该坚持使用“define disconnected”的初始肠道反应响应;)
答案 2 :(得分:2)
有几种不同的方法,但最常见的是检查发送或接收命令的结果:
nReadBytes = recv(sd, ReadBuffer, BufferSize, 0);
if (nReadBytes == SOCKET_ERROR)
{
//error
}
nSendBytes = send(sd, WriteBuffer, BufferSize, 0);
if (nSendBytes == SOCKET_ERROR)
{
//error
}
更多示例(完成错误检查,包括客户端和服务器):
答案 3 :(得分:0)
如果send()或recv()的结果是SOCKET_ERROR且WSAGetLastError()返回WSAECONNRESET,则客户端已断开连接。
来自MSDN:
WSAECONNRESET
通过对等方重置连接。
远程主机强行关闭现有连接。这个 通常在远程主机上的对等应用程序结果时生成 突然停止,主机重启,主机或远程网络 接口被禁用,或远程主机使用硬关闭(请参阅 setsockopt有关远程SO_LINGER选项的更多信息 插座)。如果由于连接断开,也可能导致此错误 保持活动活动在一个或多个操作时检测到故障 正在进行中。正在进行的操作失败了 WSAENETRESET。后续操作因WSAECONNRESET而失败。
这也适用于非阻塞套接字。
int r = recv(sock, NULL, 0, 0);
if(r == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET){
//client has disconnected!
}