Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

async await usage with TcpClient

I recently started using the new C#5.0 "async" and "await" keywords. I thought I got the twist but realized one thing that made me doubt. Here's how I was asynchronously receiving data from a remote TcpClient. Once I accept the connection I call this function :

static async void ReadAsync(TcpClient client)
{
    NetworkStream ns = client.GetStream();
    MemoryStream ms = new MemoryStream();
    byte[] buffer = new byte[1024];

    while(client.Connected)
    {
        int bytesRead = await ns.ReadAsync(buffer, 0, buffer.Length);
        ms.Write(buffer, 0, bytesRead);
        if (!ns.DataAvailable)
        {
            HandleMessage(ms.ToArray());
            ms.Seek(0, SeekOrigin.Begin);
        }
    }
}

After data is received, the loop just goes on and on without reading anything. I tested this with a Console.WriteLine in the loop. Am I using it correctly? I feel I should not be using a while loop...

like image 359
Philippe Paré Avatar asked Jun 08 '14 22:06

Philippe Paré


1 Answers

The TcpClient.Connected value is not updated immediately. According to MSDN:

true if the Client socket was connected to a remote resource as of the most recent operation; otherwise, false.

So having TcpClient.Connected as a while loop condition is not a good choice.

TcpClient.DataAvailable is used for synchronous operations and do not used for asynchronous.

Update your code to:

static async void ReadAsync(TcpClient client)
{
    NetworkStream ns = client.GetStream();
    MemoryStream ms = new MemoryStream();
    byte[] buffer = new byte[1024];

    while(true) {
        int bytesRead = await ns.ReadAsync(buffer, 0, buffer.Length);
        if (bytesRead <= 0)
            break;
        ms.Write(buffer, 0, bytesRead);
        HandleMessage(ms.ToArray());
        ms.Seek(0, SeekOrigin.Begin);
    }
}

When ReadAsync return 0, it means TCP connection closing or closed. In MSDN:

The value of the TResult parameter contains the total number of bytes read into the buffer. The result value can be less than the number of bytes requested if the number of bytes currently available is less than the requested number, or it can be 0 (zero) if the end of the stream has been reached.

like image 58
comphilip Avatar answered Oct 10 '22 11:10

comphilip