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.
You have to close the stream before closing the connection:
tcpClient.GetStream().Close();
tcpClient.Close();
Closing the client does not close the stream.
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.
Use word: using. A good habit of programming.
using (TcpClient tcpClient = new TcpClient())
{
//operations
tcpClient.Close();
}
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 })
...
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.
Closes a socket connection and allows for re-use of the socket:
tcpClient.Client.Disconnect(false);
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:
Have you tried calling TcpClient.Dispose() explicitly?
And are you sure that you have TcpClient.Close() and TcpClient.Dispose()-ed ALL connections?
client.Dispose();
client.Close();
if (stream != null)
{
clientstream.Dispose();
clientstream.Close();
}
Related
Hello and thanks for your help.
This time I would like to ask about TcpClient.
I have a server program and I am writing a client program.
This client uses TcpClient. It starts by creating a new client
clientSocket=new TcpClient();
(By the way, can this cause exceptions? just in case I put it inside a try-catch but I am not sure if that is really necessary)
Anyway, later I enter a loop and inside this loop I connect to the server
clientSocket.Connect("xx.xx.xx.xx",port);
Then I create a NetworkStream with
clientStream=clientSocket.GetStream();
and then start waiting for data from the server through Read. I know this is blocking so I also set a ReadTimeOut (say 1 second)
Anyway, so far so good.
Later if I don't receive anything from the server, I attempt to send something to it. If this keeps happening for say 3 times I want to close the connection and reconnect to the server again
(notice that a whole different problem is when the server somehow is down, cause that causes other kinds of errors in the client-perhaps I will ask about that later)
So, what do I do?
if(clientSocket.Connected)
{
Console.WriteLine("Closing the socket");
clientSocket.Close();
}
I close the socket.
The loop is finished so I go again to the beginning and try to connect to the server.
clientSocket.Connect("xx.xx.xx.xx",port);
However this causes an error(an unhandled exception actually) "Can not access a disposed object"
So my question is How can I close and reconnect to the server again??
Thanks again for any help
A TcpClient instance can only be used to connect once. You can simply instantiate a new TcpClient, rather than trying to re-open a closed one.
As explained in the other answer, a TcpClient object can only be connected once. If you want to reconnect to the server, you have to create a new TcpClient object and call Connect() again.
That said, you have a number of apparent misconceptions in your question:
First and most important, you should not use ReceiveTimeout if you have any intention whatsoever of trying to use the TcpClient object again, e.g. to send some data to the server. Once the timeout period has expired, the underlying socket is no longer usable.If you want to periodically send data to the server when the server hasn't sent data to you, you should use asynchronous I/O (which you should do anyway, in spite of the learning curve) and use a regular timer object to keep track of how long it's been since you received data from the server.
The TcpClient constructor certainly can throw an exception. At the very least, any attempt to new a reference type object could throw OutOfMemoryException, and in the case of TcpClient, it ultimately tries to create a native socket handle, which could also fail.While all I/O objects and methods can throw exceptions, you should only ever catch exceptions that you have a way to handle gracefully. So before you add a try/catch block to your code, decide what it is you want to do in the case of an exception that will ensure that your code doesn't corrupt any data and continues to operate correctly. It is generally not possible to gracefully handle OutOfMemoryException (and impractical to protect all uses of new in any case), but you certainly can catch SocketException, which could be thrown by the constructor. If that exception is thrown, you should immediately abandon the attempt to create and use TcpClient, and report the error the user so that they can attempt to correct whatever problem prevented the socket's creation.
If your server is expected to be sending you data, and you don't receive it, then closing the connection and retrying is unlikely to improve the situation. That will only cause additional load on the server, making it even more likely it will fail to respond. Likewise sending the same data over and over. You should your request once, wait as long as is practical for a response from the server, and if you get no response within the desired time, report the error to the user and let them decide what to do next.Note that in this case, you could use the ReceiveTimeout property, because all you're going to do if you don't get a response in time is abandon the connection, which is fine.
Very simple:
client.Close();
client = new TcpClient();
client.Connect(host, port);
I have a client using NamedPipeClientStream and a server using NamedPipeServerStream.
The client may start before the server, and when it call clientStream.Connect(timeout) i get TimeoutException as expected.
Is there any way I can check if there is a NamedPipeServerStream listening before calling the Connect to prevent an exception?
If someone bumps into this question five years later, this might be helpful:
var isPipeRunning = Directory.GetFiles( #"\\.\pipe\" ).Contains( $"\\.\pipe\{pipeName}" )
I suggest you should use an EventWaitHandle. On all clients, call WaitOne () and on server after opening the stream, call Set ().
So, on "server" side, write this:
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset, String.Format(#"Global\{0}", "SERVER_OPENED_HANDLE"));
OpenStream (); // inside this method you would have code that opens your named pipe for incomming messages
// finally, signal that you are done
handle.Set ();
On client side, write something like this:
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset, String.Format(#"Global\{0}", "SERVER_OPENED_HANDLE"));
// here your thread will sleep until the server calls "Set"
handle.WaitOne ();
// then you can safelly connect to the server here
ConnectToServer ();
There remains just a few situations to handle:
1) The pipe can't be opened on server becase there is already an opened pipe with the same name (will throw an exception).
2) You successfully opened the pipe, you notified clients that you are ready but after that, a milisecond after, the server crushes from some unexpected reason and the client cannot reach the server.
3) User rights problems
In all these situations, you should handle these exceptions using a try / catch and normally, if all goes well, this code will ensure that the client will NOT try to connect before the server successfully opened the pipe.
Anyway, I suggest using a more advanced technique for making IPC through Named Pipes such as using WCF or even .NET Remoting wich besides the fact that it's somehow considered obsolete by many (don't include me) is very decent at least for IPC communication. This will give you the freedom and scalability (maybe one day you will need your clients to be able to reside on other machines, and you will have to switch from IPC to a LAN communication or even in WAN / internet).
There is no way to check this only using a NamedPipeClientStream. However, you can use a Mutex like so
// In the server
var mutex = new System.Threading.Mutex(false, "MyPipeMutex");
OpenPipeAndRunServer();
mutex.Close();
// In the client process
var mutex = new System.Threading.Mutex(false, "MyPipeMutex");
if (!mutex.WaitOne(0, false))
{
OpenPipe();
}
mutex.Close();
You will probably want to wrap the Close calls in a try-finally block to make sure it always closes. In the client you can use a different timeout to actually wait for the NamedPipe to be opened.
You can also catch the exception as a work around.
I write my own telnet client. And I have one problem and cannot to solve it.
I connect to the device and communicate with it successfully, but in some moment device disconnect.
When I use Zoc terminal it write "[TELNET] INFO: DISCONNECTED" in this case.
When I use my own terminal I cannot to recognize this case. Property "Connected" in TcpClient is True. I will receive exception when I try to write something into stream after disconnection. But this is too late.
How I can recognize that connection lost?
Thanks.
Try using Socket instead of TcpClient. Some telnet daemons require each key press to flush the buffer, so try calling Stream.Flush on your relevant stream. I recommend tying a NetworkSteam to your Socket and wrapping it in a TextWriter and calling Flush on every key press.
With Socket you can recognize a lost connection by seeing that Socket.ReceiveAsync completes with success and zero bytes returned. You can also use the synchronous Socket.Receive and examine the exception that is thrown.
What I have:
I have two socket client programs written in C#.
I have one socket server program (not written by me but it works) in Python.
The problem:
The first c# socket client I wrote works fine and can communicate with the python server client. I can send data over with no issue. However I wanted to rewrite the code to make it more object oriented, so I made the second program which is the same as the first in terms of what is done.
The issue is the second one won't connect, saying this:
System.Net.Sockets.SocketException: An attempt was made to access a socket in a forbidden way by its access permissions.
I googled this and I have come to the realization that the connection from the first connection hasn't been completely unbound.
When I did a netstat -a, I actually saw the connection and it said TIME_WAIT at the end.
The question is, how do I unbind it? Is it on the C#/client side?
FYI I have already tried closing/disconnecting/shutting down the socket and none of that worked. I also put in this command
connection.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
upon instantiation of the socket connection but that did not work either.
Would I have to do something on the server side to unbind the connection?
I know you said you already calling close or disconnect.
But are you reinitializing the socket variable.
eg: connection = new System.Net.Sockets.Socket(...
If you are using an older version of .Net you may also have to call Dispose() after call Close().
eg:
connection.Close();
connection.Dispose();
connection = new System.Net.Sockets.Socket(...
Be sure to always work with sockets within try statements as any calls to send and receive data or close the socket could result it an error at which stage, you should log the error and call Close() and then if applicable Dispose() on the socket instance to clear the resources. Once this has been done, you can then reinitialize a new instance of the socket to attempt a new connection to the server.
On the client side I need to know when/if my socket connection has been broken. However the Socket.Connected property always returns true, even after the server side has been disconnected and I've tried sending data through it. Can anyone help me figure out what's going on here. I need to know when a socket has been disconnected.
Socket serverSocket = null;
TcpListener listener = new TcpListener(1530);
listener.Start();
listener.BeginAcceptSocket(new AsyncCallback(delegate(IAsyncResult result)
{
Debug.WriteLine("ACCEPTING SOCKET CONNECTION");
TcpListener currentListener = (TcpListener)result.AsyncState;
serverSocket = currentListener.EndAcceptSocket(result);
}), listener);
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be FALSE, and it is
clientSocket.Connect("localhost", 1530);
Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be TRUE, and it is
Thread.Sleep(1000);
serverSocket.Close();//closing the server socket here
Thread.Sleep(1000);
clientSocket.Send(new byte[0]);//sending data should cause the socket to update its Connected property.
Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be FALSE, but its always TRUE
After doing some testing, it appears that the documentation for Socket.Connected is wrong, or at least misleading. clientSocket.Connected will only become false after clientSocket.close() is called. I think this is a throwback to the original C Berkeley sockets API and its terminology. A socket is bound when it has a local address associated with it, and a socket is connected when it has a remote address associated with it. Even though the remote side has closed the connection, the local socket still has the association and so it is still "connected".
However, here is a method that does work:
!(socket.Poll(0, SelectMode.SelectRead) && socket.Available == 0)
It relies on that fact that a closed connection will be marked as readable even though no data is available.
If you want to detect conditions such as broken network cables or computers abruptly being turned off, the situation is a bit more complex. Under those conditions, your computer never receives a packet indicating that the socket has closed. It needs to detect that the remote side has vanished by sending packets and noticing that no response comes back. You can do this at the application level as part of your protocol, or you can use the TCP KeepAlive option. Using TCP Keep Alive from .NET isn't particularly easy; you're probably better off building a keep-alive mechanism into your protocol (alternately, you could ask a separate question for "How do I enable TCP Keep Alive in .NET and set the keep alive interval?").
Just write to your socket as normal. You'll know when it's disconnected by the Exception that says your data couldn't be delivered.
If you don't have anything to write...then who cares if it's disconnected? It may be disconnected now, but come back before you need it - why bother tearing it down, and then looping a reconnect until the link is repaired...especially when you didn't have anything to say anyway?
If it bothers you, implement a keep alive in your protocol. Then you'll have something to say every 30 seconds or so.
Maybe solution is to send some dummy data through it and check if it times out?
I recommend stripping out the higher-level language stuff and explore what happens at the lower-level IO.
The lowest I've explored was while writing isectd (find on sourceforge). Using the select() system call, a descriptor for a closed socket becomes read-ready, and when isectd would attempt the recv() the socket's disconnected state can be confirmed.
As a solution, I recommend not writing your own socket IO and use someone else's middleware. There are lots of good candidates out there. Don't forget to consider simple queuing services as well.
PS. I would have provided URLs to all the above but my reputation (1) doesn't allow it.
does the clientSocket.Send() method wait for the packet to either be ack/nack'd?
If not your code is flying onto the next line while socket is still trying to figure out what is going on.