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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/425235/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 02:53:37  来源:igfitidea点击:

How to properly and completely close/reset a TcpClient connection?

c#.nettcp

提问by TimothyP

What is the correct way to close or reset a TcpClient connection? We have software that communicates with hardware but sometimes something goes wrong and we are no longer to communicate with it, until we restart the software.

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

I have tried forcing TcpClient.Close() and even setting it to null but that doesn't work. Only a complete restart of the software works.

我曾尝试强制 TcpClient.Close() 甚至将其设置为 null 但这不起作用。只有完全重新启动软件才有效。

Suggestions?

建议?



I can't use the using keyword because TpcClient is only defined in one location, but used throughout the library. (And there is only one connection at any given time)

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

It's a library that handles communication. The software itself can call the ResetConnection() method of the Controller class (which represents the hardware).

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

It currently looks like

目前看起来像

if (tcpClient != null)
{
    tcpClient.Close();
    tcpClient = null;
}

Now from what I've read here I should use tcpClient.Dispose() instead of " = null"

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

I'll give that a try and see if it makes a difference.

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

采纳答案by Ignacio Soler Garcia

You have to close the stream before closing the connection:

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

tcpClient.GetStream().Close();
tcpClient.Close();

Closing the client does not close the stream.

关闭客户端不会关闭流。

回答by chakrit

Have you tried calling TcpClient.Dispose()explicitly?

您是否尝试过显式调用TcpClient.Dispose()

And are you sure that you have TcpClient.Close() and TcpClient.Dispose()-ed ALLconnections?

你确定你有 TcpClient.Close() 和 TcpClient.Dispose()-ed 的所有连接吗?

回答by Micha? Ziober

Use word: using. A good habit of programming.

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

using (TcpClient tcpClient = new TcpClient())
{
     //operations
     tcpClient.Close();
}

回答by jyoung

Except for some internal logging, Close == Dispose.

除了一些内部日志,Close == Dispose。

Dispose calls tcpClient.Client.Shutdown( SocketShutdown.Both ), but its eats any errors. Maybe if you call it directly, you can get some useful exception information.

Dispose 调用 tcpClient.Client.Shutdown( SocketShutdown.Both ),但它会处理任何错误。或许直接调用,可以获得一些有用的异常信息。

回答by Justin Tanner

Closes a socket connection and allows for re-use of the socket:

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

tcpClient.Client.Disconnect(false);

回答by John Demetriou

Given that the accepted answer is outdated and I see nothing in the other answers regarding this I am creating a new one. In .Net 2, and earlier, you had to manually close the stream before closing the connection. That bug is fixed in all later versions of TcpClientin C# and as stated in the doc of the Close methoda call to the method Closecloses both the connection and the stream

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

EDIT according to Microsoft Docs

根据 Microsoft Docs 进行编辑

The Close method marks the instance as disposed and requests that the associated Socket close the TCP connection. Based on the LingerState property, the TCP connection may stay open for some time after the Close method is called when data remains to be sent. There is no notification provided when the underlying connection has completed closing.

Close 方法将实例标记为已释放并请求关联的 Socket 关闭 TCP 连接。根据Ling​​erState 属性,当数据仍有待发送时,在调用Close 方法后,TCP 连接可能会保持打开状态一段时间。底层连接完成关闭时不提供通知。

Calling this method will eventually result in the close of the associated Socket and will also close the associated NetworkStream that is used to send and receive data if one was created.

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

回答by Kevin Gigiano

The correct way to close the socket so you can re-open is:

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

tcpClient.Client.Disconnect(true);

The Boolean parameter indicates if you want to reuse the socket:

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

Disconnect method usage

断开连接方法的使用

回答by Ian Mercer

Despite having all the appropriate usingstatements, calling Close, having some exponential back off logic and recreating the TcpClientI've still been seeing issues where the application cannot recover the TCP connection without an application restart. It keeps failing with a System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

尽管有所有适当的using语句,调用Close,具有一些指数回退逻辑并重新创建TcpClient我仍然看到应用程序无法在不重新启动应用程序的情况下恢复 TCP 连接的问题。它一直以 System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

But there is an option LingerStateon the TcpClientthat appears it may have solved the issue (might not know for a few months as my own hardware setup only fails about that often!). See MSDN.

但是,有一个选项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 })
   ...