TcpClient; NetworkStream; ReadAsync; C# [英] TcpClient; NetworkStream; ReadAsync; C#

查看:423
本文介绍了TcpClient; NetworkStream; ReadAsync; C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请原谅我缺乏有关任务和异步的知识.

Please excuse my lack of knowledge regarding Tasks and Async.

使用TcpClient类,我正在与可用服务器建立连接:

Using the TcpClient class I am creating a connection with an available server:

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)将执行假定的任务.

The helper methods HandleException(Exception ex) and HandleInboundData(byte[] buffer, int length) will perform the assumed tasks.

与服务器的连接将永久存在,并且从服务器接收的数据将具有未知的长度和频率,其想法是将任务丢在那里,仅在数据可用时才接收和处理入站数据.

The connection to the server will be in perpetuity and the data received from the server will be of unknown length and frequency, the idea being to throw a task out there that receives and processes the inbound data only when data is available.

ReadClientAsync(TcpClient client)显然是失败的,因为如果没有可用数据,ReadAsync将始终返回0字节.

ReadClientAsync(TcpClient client) is an obvious fail because ReadAsync will always return 0 bytes if there is no data available.

我应该如何使用异步/任务来编写ReadClientAsync,以防止出现繁忙循环的情况?我以前在这些情况下使用过BeginRead/EndRead,效果很好.在这种特殊情况下会是解决方案吗?

How should I approach writing ReadClientAsync using async / task to prevent the busy-looping situation? I've used BeginRead / EndRead in these situations before, which has worked fine. Would that be the solution in this particular case?

谢谢

推荐答案

不,这不是TCP的工作原理.

No, that's not how TCP works.

NetworkStream被视为处于流结束"状态.那就是ReadAsync(或者说Read)返回零的情况-在任何其他情况下都不会.

NetworkStream is considered to be in an "end of stream" state when the other side has initiated (possible one-way) shutdown. That's when ReadAsync (or Read, for that matter) returns zero - not in any other case.

MSDN文档很容易被误解-主要是因为您查找的文档不正确. NetworkStream不会覆盖ReadAsync(没有理由这样做),因此实际上您正在查看通用Stream.ReadAsync的文档.相反,NetworkStream.Read的文档说:

The MSDN documentation can be easily misunderstood - mainly because you're looking at the wrong piece of documentation. NetworkStream doesn't override ReadAsync (there's no reason to do so), so you're actually looking at the documentation for the generic Stream.ReadAsync. In contrast, the documentation for NetworkStream.Read says:

此方法将数据读入buffer参数并返回成功读取的字节数.如果没有数据可读取,则Read方法将返回0.Read操作将读取尽可能多的数据,直到size参数指定的字节数为止.如果远程主机关闭了连接,并且已收到所有可用数据,则Read方法将立即完成并返回零字节.

This method reads data into the buffer parameter and returns the number of bytes successfully read. If no data is available for reading, the Read method returns 0. The Read operation reads as much data as is available, up to the number of bytes specified by the size parameter. If the remote host shuts down the connection, and all available data has been received, the Read method completes immediately and return zero bytes.

请注意最后一句话,它告诉您NetworkStream成为流的末尾"的实际含义.这就是TCP连接关闭的方式.

Note the final sentence, which tells you what it actually means for a NetworkStream to be "end of stream". This is how TCP connections are closed.

您对此的响应通常也应该从另一端断开连接-return使用辅助方法并清理套接字.无论如何,不​​要再重复while (true) -您将得到一个无限循环,占用100%的CPU.

Your response to this should usually be shutting down the connection from the other side as well - return out of your helper method and clean up the socket. In any case, do not repeat the while (true) again - you're just going to get an infinite loop that eats 100% of your CPU.

如果您想获得有关如何使用await处理C#异步套接字的一些指导,请在

If you want a few pointers on how to handle C# asynchronous sockets with await, have a look at my sample at https://github.com/Luaancz/Networking/tree/master/Networking%20Part%202. Note the disclaimers - this is in no way production ready. But it does solve a few of the very common mistakes people make when implementing TCP communication.

这篇关于TcpClient; NetworkStream; ReadAsync; C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆