我最近开始使用新的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循环...
答案 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个字节,表示要传输的数据长度。