当前位置:  开发笔记 > 编程语言 > 正文

TcpClient; NetworkStream; ReadAsync; C#

如何解决《TcpClient;NetworkStream;ReadAsync;C#》经验,为你挑选了1个好方法。

请原谅我对任务和异步的知识不足。

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

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字节。

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

谢谢,



1> Luaan..:

不,这不是TCP的工作方式。

NetworkStream当另一侧启动(可能是单向)关闭时,则被视为处于“流结束”状态。那是ReadAsync(或Read就此而言)返回零的时间-在任何其他情况下都不会。

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

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

请注意最后一句话,它告诉您NetworkStream“结束播放”的实际含义。这就是关闭TCP连接的方式。

您对此的反应通常还应该从另一端关闭连接-使用return辅助方法并清理套接字。无论如何,请勿重复while (true)要再一次-您将得到一个无限循环,该循环占用100%的CPU。

如果您想获得有关如何使用C#异步套接字的一些指导await,请参阅https://github.com/Luaancz/Networking/tree/master/Networking%20Part%202上的示例。请注意免责声明-绝不准备生产。但这确实解决了人们在实现TCP通信时常犯的一些错误。

推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有