检测关闭的网络连接

我写过一些通过TCP进行通信的小程序。 由于一个程序已关闭其网络连接,而另一个端点以某种方式未能注意到它现在已断开连接,因此系统挂起时存在无穷无尽的问题。

我期待在已关闭的TCP连接上进行I / O以抛出某种I / Oexception,但是程序似乎只是挂起 ,等待另一个端点回复。 显然,如果连接已关闭,则该回复永远不会到来。 (如果你把它留下来,比如20分钟,它似乎没有超时。)

有什么方法可以强制远程端“看到”我已关闭网络连接?

更新:这是一些代码……

public sealed class Client { public void Connect(IPAddress target) { var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(ipAddress, 1177); _stream = new NetworkStream(socket); } public void Disconnect() { _stream.Close(); } } public sealed class Server { public void Listen() { var listener = new TcpListener(IPAddress.Any, 1177); listener.Start(); var socket = listener.AcceptSocket(); _stream = new NetworkStream(socket); ... } public void Disconnect() { socket.Shutdown(SocketShutdown.Both); socket.Disconnect(false); } } 

当应用程序以正确的方式关闭套接字时,它会发送包含0个字节的消息。 在某些情况下,您可能会收到SocketException表明出现了问题。 在第三种情况下,远程方不再连接(例如通过拔出网络电缆)而没有双方之间的任何通信。

如果最后发生这种情况,您必须将数据写入套接字以检测您是否无法再访问远程方。 这就是发明保持活动机制的原因 – 它们经常检查它们是否仍能与另一方通信。

查看您现在发布的代码:使用NetworkStream时,对它的Read操作将返回值0(字节)以指示客户端已关闭连接。

文档提到两者

“如果没有可用于读取的数据,则Read方法返回0.”

“如果远程主机关闭连接,并且已收到所有可用数据,则Read方法立即完成并返回零字节。”

在同一段中。 实际上,如果在连接打开时没有可用于读取的数据, NetworkStream阻止。

您好MathematicalOrchid,

你可能会在这里找到你想要的东西:

http://blog.stephencleary.com/2009/05/detection-of-half-open-dropped.html

在处理TCP套接字和检测半开连接时,有一些很好的信息。

你也可以参考这篇似乎有相同解决方案的post:

TcpClient与服务器通信以保持c#中的活动连接?

戴夫

您正在打开套接字,并将其分配给流。 在该过程结束时,您关闭网络流,但不关闭套接字。

要使NetworkStream.Close()关闭底层套接字,必须在构造函数中将所有权参数设置为true – 请参阅http://msdn.microsoft.com/en-us/library/te7e60bx.aspx上的 MSDN Docs。

这可能导致连接挂起,因为底层套接字未正确关闭。

更改

 _stream = new NetworkStream(socket); 

 _stream = new NetworkStream(socket, true); 

另外,如果您的小应用程序不需要最高性能,则应尝试使用TCPClienthttp://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient%28v= vs.100%29.aspx 。 这是套接字的包装器,它提供连接状态检查function。