TCP客户;网络流;ReadAsync;C#
请原谅我缺乏关于任务和异步的知识 使用TcpClient类,我正在创建与可用服务器的连接:TCP客户;网络流;ReadAsync;C#,c#,tcpclient,beginread,C#,Tcpclient,Beginread,请原谅我缺乏关于任务和异步的知识 使用TcpClient类,我正在创建与可用服务器的连接: void async RunClientAsync() { TcpClient client = new TcpClient(); try { await client.ConnectAsync(IPAddress.Parse("1.1.1.1"), 8889); Task.Start(() => ReadClientAsync(client)
void async RunClientAsync()
{
TcpClient client = new TcpClient();
try
{
await client.ConnectAsync(IPAddress.Parse("1.1.1.1"), 8889);
Task.Start(() => ReadClientAsync(client));
}
catch (Exception ex)
{
HandleException(ex);
}
}
// -----
void async ReadClientAsync(TcpClient client)
{
byte[] bf = new byte[2048];
try
{
while(true)
{
int br = await client.NetworkStream().ReadAsync();
if (br > 0)
{
HandleInboundData(bf, br);
}
}
}
catch (Exception ex)
{
HandleException(ex);
}
}
助手方法HandleException(Exception ex)和HandleInboundData(byte[]buffer,int length)将执行假定的任务
与服务器的连接将是永久性的,从服务器接收的数据的长度和频率未知,其想法是抛出一个任务,该任务仅在数据可用时接收和处理入站数据
ReadClientAsync(TcpClient client)显然失败,因为如果没有可用数据,ReadAsync将始终返回0字节
我应该如何使用async/task编写ReadClientAsync来防止繁忙的循环情况?我以前在这些情况下使用过BeginRead/EndRead,效果很好。在这种特殊情况下,这就是解决方案吗
谢谢,不,TCP不是这样工作的
NetworkStream
被认为在另一方启动(可能是单向)关机时处于“流结束”状态。这就是ReadAsync
(或Read
)返回零的时候,而不是在任何其他情况下
MSDN文档很容易被误解——主要是因为您看到的文档是错误的NetworkStream
不会覆盖ReadAsync
(没有理由这样做),因此您实际上正在查看通用流的文档。ReadAsync
。相比之下,NetworkStream.Read
的文档说明:
此方法将数据读入缓冲区参数,并返回成功读取的字节数。如果没有可读取的数据,Read方法返回0。读取操作读取尽可能多的可用数据,最大读取量为size参数指定的字节数。如果远程主机关闭连接,并且已收到所有可用数据,则读取方法立即完成并返回零字节
请注意最后一句,它告诉您网络流
为“流的结束”的实际含义。这就是TCP连接关闭的方式
对此的响应通常也应该是关闭另一端的连接-从helper方法返回
,并清理套接字。在任何情况下,不要再次重复while(true)
——您只会得到一个占用100%CPU的无限循环
如果您想要一些关于如何使用
wait
处理C#异步套接字的指南,请查看我的示例。请注意免责声明-这绝不是生产准备就绪。但它确实解决了人们在实现TCP通信时经常犯的一些错误。谢谢您的评论。这来自ReadAsync的MSDN条目:“表示异步读取操作的任务。TResult参数的值包含读入缓冲区的总字节数。如果当前可用字节数小于请求的字节数,则结果值可以小于请求的字节数,也可以为0(零)如果已到达流的末端。“我理解“流结束”意味着流中没有要读取的数据。理解。谢谢Luaan。我相信我理解问题所在。您如何在10秒后超时以使ReadAsync或WriteAsync或ConnectAsync超时。换句话说,它们要么成功完成,要么在10秒后超时?