Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TcpClient: How do I close and reconnect it again?

Tags:

c#

tcpclient

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

like image 382
KansaiRobot Avatar asked Sep 09 '16 00:09

KansaiRobot


2 Answers

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.

like image 200
Curtis Lusmore Avatar answered Sep 26 '22 02:09

Curtis Lusmore


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:

  1. 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.
  2. 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.
  3. 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.
like image 36
Peter Duniho Avatar answered Sep 25 '22 02:09

Peter Duniho