0

I am using Asynchronous TCP server/client communication. I have noticed in my log that the same client reconnects several times. However, it never shows that it was disconnected. My code has logging for both connection and disconnection. So why does readAsync stay in loop while the client has disconnected? Here is the code for your reference:

   private async Task Accept(TcpClient client)
    {
       //get client information 
        string clientEndPoint = GetClientIPAddress(client);          
        log.Info("Client connected at " + clientEndPoint); //same client is connected several times in log

        await Task.Yield (); 

        try 
        {              
            using (client) 
            using (NetworkStream stream = client.GetStream ()) 
            { 
                byte[] dataReceived = new byte [100];                  
                while (await stream.ReadAsync(dataReceived, 0, dataReceived.Length) != 0) //read input stream  -  0=>end of stream is reached
                {                    
                    //pass on data for processing                      
                    var task = ProcessData(dataReceived);   
                }                   
            }
            log.Info("Closing client connection " + clientEndPoint);//this line is never reached in log
            if (client.Connected)
                client.Close();
        } //end try
        catch (Exception ex) 
        {
            log.Error(ex.Message);
            log.Info("Closing client connection " + clientEndPoint);
            if (client.Connected)
                client.Close();
        }
4
  • 1
    Are you aware that you have a race condition here? var task = ProcessData(dataReceived);. You start reading into the same buffer that is being processed at the moment. Commented Apr 8, 2014 at 12:28
  • No I am not aware of that. How can I avoid it? Commented Apr 8, 2014 at 15:38
  • By not running ProcessData concurrently with reading. This is not necessary anyway because the TCP stack buffers for you asynchronously. Add an await. Commented Apr 8, 2014 at 15:40
  • ok thanks! I did that. Commented Apr 8, 2014 at 15:57

2 Answers 2

3

It looks like you may have a half-open problem. You should periodically write data to determine whether the socket is still connected; reads can detect graceful shutdowns but not half-open scenarios.

I describe the half-open problem more on my blog.

Sign up to request clarification or add additional context in comments.

1 Comment

Yes, it's the problem. The router on the other side is rebooting after certain interval. After reboot it starts a new connection with the server. The server accepts it as a new client. On the other hand, it still has old connection left open and waiting for data on old thread.
0

Did you check if TCP keep alive is set? That should detect if connection is broken.

Also, check if you got zero length bytes on receive, this means that connection is closed.

Edit: Keep Alive is standard method to check if connection is active, this means that one side sends small chunks of data to the other side periodically: http://en.wikipedia.org/wiki/Keepalive.

Many components have this feature already implemented. I've never used TcpClient class, but it must be some wrapper class for Socket over TCP and, as doc states, this class have exposed underlaying Socket (you can use Socket class for TCP also, but never mind). And this Socket have method SetSocketOption. So try:

client.Socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true);

4 Comments

1. How do I check if TCP keep alive is set? Can I please have some sample code?
2. Isn't while (await stream.ReadAsync(dataReceived, 0, dataReceived.Length) != 0) checking if data stream length is zero then get out of the loop?
Of course, if you never read zero bytes, then it's probably that remote host didn't closed connection gracefully.
Thanks for sample code! Although your answer describes the solution I accepted the other comment as answer because the link in it explains the cause of this problem with 4 different solutions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.