如何在C++中通过Winsock检查客户端是否已断开连接?

19

如何在C++中通过Winsock检查客户端是否已断开连接?


你想从服务器端知道客户端套接字是否仍然连接着吗? - Brian R. Bondy
定义 'disconnected' ;) - Len Holgate
另一端的端口由于某种原因关闭了。 - Sasha
请参考我帖子中的链接,常见问题解答中列举了其他大部分检查断开连接的方法。 - sfossen
4个回答

13

Beej的网络编程指南

如果您以阻塞模式调用recv,并返回0个字节读取,则套接字已断开连接,否则它会等待接收到字节。

请参阅FAQ 2.12

页面上的select示例。

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
    }
}

BSD套接字,它们被广泛应用。 - Brian R. Bondy

7
只有尝试发送数据才能确定TCP套接字是否“断开连接”。这是因为协议设计允许对等方之间的暂时中断。因此,如果您从A通过R1通过R2通过R3连接到B并发送数据一段时间后停止发送,则可以拔下R2-> R3(例如),A和B都不会注意到(或关心)。如果然后将R2-> R4和R4-> R3插入并尝试在A和B之间发送数据,则所有事情都将“正常工作”,您永远不会知道。但是,如果在R2-> R3断开连接时尝试发送数据,则最终(在所有TCP级重试之后)会收到错误信息。
现在,某些操作系统可能能够提醒您本地网络适配器当前未连接,并且您可以使用它来表示“我不再与我的对等方连接”,但我不建议这样做。
如果让对等方知道连接何时“断开”很重要,则使用应用程序级别的“ping”消息定期在对等方之间发送数据或使用TCP keep-alive。就个人而言,我会选择ping消息...
编辑:当然,所有这一切都假定您想知道是否仍然可以在连接上发送数据,毕竟,当客户端不再发送数据时,您会被告知,因为您的读取将返回0字节,并且您知道当它断开其发送端时,您的写入将失败;您还知道何时关闭连接的发送或接收端口...
我想我应该坚持最初的直觉反应“定义断开连接”;)

2

有几种不同的方法,但最常见的是检查发送或接收命令的结果:

 nReadBytes = recv(sd, ReadBuffer, BufferSize, 0);
 if (nReadBytes == SOCKET_ERROR)
 {
     //error
 }
 nSendBytes = send(sd, WriteBuffer, BufferSize, 0);
 if (nSendBytes == SOCKET_ERROR)
 {
     //error
 }

这里有更多的示例(包括客户端和服务器的错误检查):

http://tangentsoft.net/wskfaq/examples/basics/


1
如果send()或recv()的结果为SOCKET_ERROR,并且WSAGetLastError()返回WSAECONNRESET,则客户端已断开连接。
来自MSDN:

WSAECONNRESET

对等方重置连接。

现有的连接被远程主机强制关闭。这通常是由于远程主机上的对等应用程序突然停止、主机重新启动、主机或远程网络接口禁用或远程主机使用硬关闭(有关SO_LINGER选项的更多信息,请参见setsockopt)而导致的。如果一个或多个操作正在进行中,那么此错误也可能是由于保持活动检测到失败而导致连接中断。正在进行的操作将以WSAENETRESET失败。随后的操作将以WSAECONNRESET失败。

非阻塞套接字也适用。

int r = recv(sock, NULL, 0, 0);
if(r == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET){
    //client has disconnected!
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接