异步等待使用TcpClient

时间:2014-06-08 22:44:27

标签: c# asynchronous tcp

我最近开始使用新的C#5.0“async”和“await”关键字。我以为我得到了扭曲,但意识到有一件事让我怀疑。这是我从远程TcpClient异步接收数据的方式。一旦我接受连接,我就称之为函数:

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);
        }
    }
}

收到数据后,循环只会继续打开而不会读取任何内容。我在循环中用Console.WriteLine测试了这个。我正确使用它吗?我觉得我不应该使用while循环...

2 个答案:

答案 0 :(得分:4)

TcpClient.Connected值不会立即更新。根据MSDN:

  

true如果客户端套接字从最近操作开始连接到远程资源;否则,false

因此将TcpClient.Connected作为while循环条件不是一个好的选择。

TcpClient.DataAvailable用于同步操作,不用于异步。

将您的代码更新为:

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);
    }
}

ReadAsync返回0时,表示TCP连接关闭或关闭。在MSDN中:

  

TResult参数的值包含读入缓冲区的总字节数。如果当前可用的字节数小于请求的数字,则结果值可以小于请求的字节数,如果已到达流的末尾,则结果值可以为0(零)。

答案 1 :(得分:0)

我最终使用了长度加前缀的消息,每个数据包前加4个字节,表示要传输的数据长度。