日期:2014-05-17  浏览次数:23092 次

C# TcpClient如何判断对方是否断开连接(包括物理网络不通、关闭套接字等)
如题,C# TcpClient如何判断对方是否断开连接(包括物理网络不通、对方关闭套接字等)?

先列出我自己已经找到的资料:(TcpClient.Client的类型为System.Net.Sockets.Socket)

1. TcpClient.Connected: 属性获取截止到最后一次 I/O 操作时的 Client 套接字的连接状态。
2. TcpClient.Client.Connected: 属性获取截止到最后的 I/O 操作时 Socket 的连接状态。Connected 属性的值反映最近操作时的连接状态。 如果您需要确定连接的当前状态,请进行非阻止、零字节的 Send 调用。 如果该调用成功返回或引发 WAEWOULDBLOCK 错误代码 (10035),则该套接字仍然处于连接状态;否则,该套接字不再处于连接状态。(MSDN上还有一段代码)
3. TcpClient.Available: 如果远程主机处于关机状态或关闭了连接,Available 可能会引发 SocketException。
4. TcpClient.Client.Available: 如果远程主机处于关机状态或关闭了连接,则 Available 会引发 SocketException。
5. Socket.Poll:  http://msdn.microsoft.com/zh-cn/library/vstudio/system.net.sockets.socket.poll(v=vs.100).aspx (主要看Mode为SelectRead时Poll的返回值)
6. 有网友提供如下方法:

if (s.Poll(-1, SelectMode.SelectRead))
{
   int nRead = s.Receive();
   if (nRead == 0)
   {
     //socket连接已断开
   }
}


我自己通过测试得出的结论:

1. 根据TcpClient.Client.Connected后面的说明和MSDN上的代码写出的检测代码只能判断对方由连接状态直接关闭软件! 不能检测出对方断开连接(tcpClient.Close)!
2. 根据TcpClient.Client.Available后面的说明做验证,发现当对方关闭了连接后获取Available还是不回引发异常!
3. 经测试,上述网友提供的方法倒是可以检测 物理网络不通、对方关闭套接字 !但是网上有人说,即使网络正常nRead也可能为0!这种情况我还没有遇到过,但我不知道这种方法是否合理!请大牛们指点迷津...

上面说了这么多,其实也就是想问有没有更好或者更为严谨的方法来判断对方是否断开连接(包括物理网络不通、对方关闭套接字等)?

------解决方案--------------------
你贴出的msdn不是已经说明了嘛!
------解决方案--------------------
正常的Receive是在子线程里的,无需你所谓的那种“检测”流程。在Receive出现异常时就完全终止接受就行了。

如果你非要去额外地“检测”,msdn说的很明确“如果您需要确定连接的当前状态,请进行非阻止、零字节的 Send 调用”。
------解决方案--------------------
引用:
如题,C# TcpClient如何判断对方是否断开连接(包括物理网络不通、对方关闭套接字等)?

先列出我自己已经找到的资料:(TcpClient.Client的类型为System.Net.Sockets.Socket)

1. TcpClient.Connected: 属性获取截止到最后一次 I/O 操作时的 Client 套接字的连接状态。
2. TcpClient.Client.Connected: 属性获取截止到最后的 I/O 操作时 Socket 的连接状态。Connected 属性的值反映最近操作时的连接状态。 如果您需要确定连接的当前状态,请进行非阻止、零字节的 Send 调用。 如果该调用成功返回或引发 WAEWOULDBLOCK 错误代码 (10035),则该套接字仍然处于连接状态;否则,该套接字不再处于连接状态。(MSDN上还有一段代码)