如何正确完全关闭/重置TcpClient连接?

Tim*_*hyP 69 .net c# tcp

关闭或重置TcpClient连接的正确方法是什么?我们有软件与硬件通信,但有时出现问题,我们不再与它通信,直到我们重新启动软件.

我已经尝试强制TcpClient.Close(),甚至将其设置为null但这不起作用.只有完全重启软件才能运行.

建议?


我不能使用using关键字,因为TpcClient仅在一个位置定义,但在整个库中使用.(并且在任何给定时间只有一个连接)

它是一个处理通信的库.软件本身可以调用Controller类的ResetConnection()方法(代表硬件).

它目前看起来像

if (tcpClient != null)
{
    tcpClient.Close();
    tcpClient = null;
}
Run Code Online (Sandbox Code Playgroud)

现在从我在这里读到的,我应该使用tcpClient.Dispose()而不是"= null"

我会尝试一下,看看它是否有所作为.

Ign*_*cia 81

您必须在关闭连接之前关闭流:

tcpClient.GetStream().Close();
tcpClient.Close();
Run Code Online (Sandbox Code Playgroud)

关闭客户端不会关闭流.

  • 请注意,必须关闭流的bug([support.microsoft.com/kb/821625 ](http://support.microsoft.com/kb/821625))仅存在于.NET 1.1及更早版本中.我在.NET 4.5中测试了示例代码,并且它可以正常工作而无需在流上调用close. (33认同)
  • 如果关闭TcpClient没有关闭连接,它到底是什么关闭?有没有理由关闭TcpClient? (8认同)
  • 如果我使用tcpClient.Close()而不是tcpClient.Client.Close()或tcpClient.GetStream().Close(),我仍然会在.NET 4.6.1上遇到间歇性问题.前几天我几乎失去了理智,直到找到了这个. (3认同)

Mic*_*ber 21

用词:using.编程的好习惯.

using (TcpClient tcpClient = new TcpClient())
{
     //operations
     tcpClient.Close();
}
Run Code Online (Sandbox Code Playgroud)

  • 并非适用于所有型号.如果您在一个代码块中临时使用连接但是如果您的客户端实现想要将连接保持为成员,则此方法很有用,此方法将失败.您还会发现,根据类文档,在TcpClient上调用Dispose()不会关闭底层套接字.使用只会处置. (39认同)
  • @Gusdor查看反射源,似乎Dispose(true)将在客户端上调用Close().(.NET 4.0) (7认同)

Joh*_*iou 21

鉴于接受的答案已经过时,我在其他答案中没有看到任何关于此的答案,我正在创建一个新答案.在.Net 2和更早版本中,您必须在关闭连接之前手动关闭流.该错误TcpClient在C#的所有更高版本中得到修复,并且如Close方法的文档中所述,对方法的调用会Close关闭连接和流

编辑根据Microsoft Docs

Close方法将实例标记为已释放,并请求关联的Socket关闭TCP连接.基于LingerState属性,在仍需要发送数据时调用Close方法后,TCP连接可能会保持打开一段时间.底层连接完成关闭时没有提供通知.

调用此方法最终将导致关联的Socket关闭,并且还将关闭用于发送和接收数据的关联NetworkStream(如果已创建).


Jus*_*ner 7

关闭套接字连接并允许重新使用套接字:

tcpClient.Client.Disconnect(false);
Run Code Online (Sandbox Code Playgroud)

  • 你的意思是断开连接(真的)? (5认同)

jyo*_*ung 5

除某些内部日志记录外,关闭==处置。

处置调用tcpClient.Client.Shutdown(SocketShutdown.Both),但是会占用任何错误。也许如果直接调用它,可以获得一些有用的异常信息。


小智 5

关闭套接字以便重新打开的正确方法是:

tcpClient.Client.Disconnect(true);
Run Code Online (Sandbox Code Playgroud)

Boolean参数指示是否要重用套接字:

断开方法的使用


Ian*_*cer 5

尽管拥有所有适当的using语句,但调用Close,具有一些指数退避逻辑并重新创建TcpClientI,我仍然看到问题,即如果应用程序不重新启动,应用程序将无法恢复TCP连接。它不断失败 System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host

但是,有一个选项LingerStateTcpClient出现可能已经解决了这个问题(可能不知道几个月我自己的硬件设置不仅不能对经常!)。参见MSDN

// This discards any pending data and Winsock resets the connection.
LingerOption lingerOption = new LingerOption(true, 0);

using (var tcpClient = new TcpClient 
       {SendTimeout = 2000, ReceiveTimeout = 2000, LingerState = lingerOption })
   ...
Run Code Online (Sandbox Code Playgroud)