简体   繁体   English

与TcpClient异步等待使用

[英]async await usage with TcpClient

I recently started using the new C#5.0 "async" and "await" keywords. 我最近开始使用新的C#5.0“ async”和“ await”关键字。 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. 这是我从远程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. 我在循环中使用Console.WriteLine进行了测试。 Am I using it correctly? 我使用正确吗? I feel I should not be using a while loop... 我觉得我不应该使用while循环...

The TcpClient.Connected value is not updated immediately. TcpClient.Connected值不会立即更新。 According to MSDN: 根据MSDN:

true if the Client socket was connected to a remote resource as of the most recent operation; 如果从最近一次操作开始,客户端套接字已连接到远程资源,则为true否则为true otherwise, false . 否则为false

So having TcpClient.Connected as a while loop condition is not a good choice. 因此,将TcpClient.Connected作为while循环条件不是一个好选择。

TcpClient.DataAvailable is used for synchronous operations and do not used for asynchronous. TcpClient.DataAvailable用于同步操作,而不用于异步。

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. ReadAsync返回0时,表示TCP连接关闭或关闭。 In MSDN: 在MSDN中:

The value of the TResult parameter contains the total number of bytes read into the buffer. TResult参数的值包含读入缓冲区的字节总数。 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. 如果当前可用的字节数小于请求的数目,则结果值可以小于请求的字节数;如果已到达流的末尾,则结果值可以为0(零)。

我最终使用了带有长度前缀的消息,在每个数据包之前以4个字节作为前缀,以表示即将到来的数据的长度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM