检测关闭的网络连接

时间:2013-09-17 09:46:24

标签: c# tcp

我写了很多通过TCP进行通信的小程序。由于一个程序已关闭其网络连接,而另一个端点无法注意它现在已断开连接,我在系统挂起时遇到了无数问题。

我期待在已关闭的TCP连接上进行I / O以抛出某种I / O异常,但是程序似乎只是挂起,等待另一端的永远点回复。显然,如果连接已关闭,则该回复永远不会到来。 (如果你把它留下来,比如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);
  }
}

3 个答案:

答案 0 :(得分:2)

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

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

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

documentation提及

  

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

  

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

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

答案 1 :(得分:1)

Hi MathematicalOrchid,

您可以在这里找到您要找的内容:

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

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

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

TcpClient communication with server to keep alive connection in c#?

-Dave

答案 2 :(得分:1)

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

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

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

更改

_stream = new NetworkStream(socket);

_stream = new NetworkStream(socket, true);

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