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

C#.NetTcp

C# Problem Overview


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.

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.

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)

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

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"

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

C# Solutions


Solution 1 - C#

You have to close the stream before closing the connection:

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

Closing the client does not close the stream.

Solution 2 - C#

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 TcpClient in C# and as stated in the doc of the Close method a call to the method Close closes both the connection and the stream

EDIT according to 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.

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.

Solution 3 - C#

Use word: using. A good habit of programming.

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

Solution 4 - C#

Despite having all the appropriate using statements, calling Close, having some exponential back off logic and recreating the TcpClient I'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.

But there is an option LingerState on the TcpClient that 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.

// 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 })
   ...

Solution 5 - C#

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

tcpClient.Client.Disconnect(false);

Solution 6 - C#

Except for some internal logging, 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.

Solution 7 - C#

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:

Disconnect method usage

Solution 8 - C#

Have you tried calling TcpClient.Dispose() explicitly?

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTimothyPView Question on Stackoverflow
Solution 1 - C#Ignacio Soler GarciaView Answer on Stackoverflow
Solution 2 - C#John DemetriouView Answer on Stackoverflow
Solution 3 - C#Michał ZioberView Answer on Stackoverflow
Solution 4 - C#Ian MercerView Answer on Stackoverflow
Solution 5 - C#Justin TannerView Answer on Stackoverflow
Solution 6 - C#jyoungView Answer on Stackoverflow
Solution 7 - C#Kevin GigianoView Answer on Stackoverflow
Solution 8 - C#chakritView Answer on Stackoverflow