如何检测断开连接的套接字C#?

我一直在使用C#中的套接字客户端程序,并且想知道如何检测套接字的另一端何时“不正常”地断开连接,就像拔出网络电缆或硬重置一样。

我在下面有这些函数来访问套接字,根据这里的SO问题和这篇MSDN文章 ,检查断开连接套接字的最佳方法是发送长度为0的1字节消息。如果抛出exception并且WSAEWOULDBLOCK不是错误代码,然后套接字断开连接。 我试过这个但是在硬重置服务器连接之后,客户端将调用Send(new byte[1], 0, 0, SocketFlags.None)并成功返回,并且之后的Receive()命令返回WSAEWOULDBLOCK错误。

是什么赋予了??

这是我的代码如下。 _socket设置为非阻塞模式:

 private int nonBlockRecv(byte[] recvBytes, int offset, int size, SocketFlags sf) { int bytesRecv = 0; while (true) { try { nonBlockSend(new byte[1], 0, 0, sf); bytesRecv = _socket.Receive(recvBytes, offset, size, sf); break; } catch (SocketException excp) { if (excp.ErrorCode != 10035) // WSAEWOULDBLOCK throw excp; } } return bytesRecv; } private int nonBlockSend(byte[] sendBytes, int offset, int size, SocketFlags sf) { int bytesSent = 0; while (true) { try { _socket.Send(sendBytes, offset, size, sf); break; } catch (SocketException excp) { if (excp.ErrorCode != 10035) // WSAEWOULDBLOCK throw excp; } } return bytesSent; } 

编辑:这可能是有益的,但服务器是Windows Mobile设备。 我在另一个线程中读到,不同的OS可能会在它们死亡时发送套接字关闭信号。 也许Windows Mobile OS不这样做?

如果远程计算机正常断开会话连接, Socket.Receive()方法将返回0字节。 您必须检测到该信息才能知道远程端已断开连接:

 int recv = sock.Receive(data); if (recv == 0) { // Remote client has disconnected. } else { // Remote client has sent data. } 

此外,即使出现SocketException ,您也可以识别套接字断开的exception。

希望这有助于解决您的问题。

我知道这已经很晚了,但我想出了一个狡猾的解决方案。

我不得不与第三方软件进行通信,该软件期望在发送的每个命令上都有回车符,否则它会忽略它。

在主要阶段,我的客户端套接字处于循环中,接收来自第三方软件的响应。 我的解决方案并不理想,但基本前提是我在套接字上设置接收超时,以便循环尝试读取5秒然后落入catch,然后再循环。 在每次接收之前,我调用我自己的isconnected方法,该方法执行一个没有回车的小写,所以它被第三方软件忽略,但如果网络丢失,它将给我一个可靠的失败。 如果写入失败,我所做的就是抛出一个LostConnectionException并在外部处理它。

如果你正在编写服务器和客户端,你可以很容易地想出一个另一个忽略的checkdigit。

这可能不完美但对我来说可靠。

 while (numberOfBytesRead == 0) { try { IsConnected(); _socket.ReceiveTimeout = 5000; numberOfBytesRead = _socket.Receive(myReadBuffer, 0, myReadBuffer.Length, SocketFlags.None); } catch (Exception e) { if (e.GetType() == typeof (LostConnection)) { Status = SocketStatus.offline; throw; } } } 

并且isconnected方法看起来像这样

 public bool IsConnected(Socket s) { try { ASCIIEncoding encoder = new ASCIIEncoding(); byte[] buffer = encoder.GetBytes("test"); s.Send(buffer, 0, buffer.Length, SocketFlags.None); } catch (Exception) { throw new LostConnection(); } return s.Connected; }