【问题标题】:C# How should I use NetworkStream more effectively?C# 我应该如何更有效地使用 NetworkStream?
【发布时间】:2017-04-22 00:55:07
【问题描述】:

数据包通过NetworkStreamTcpListener发送到TcpClient。数据包不大(5 字节),但频率很高(大约每秒 1000 个或更多)。你能给我建议我应该如何最有效地处理它吗?现在我使用 async 来获取流,填充缓冲区,然后将其剪切到数据包中。之后重复该过程。但 在某些时候我会失去真正的顺序。

s 是 NetworkStream。

数据包有2个字段:type(1 Byte (byte))和value(4 Bytes (int))

MAXVALUEPACKET = 4096

客户代码:

async Task process()
    {
        bool flag = false;
        while (true)
        {
            byte[] actionBuffer;
            flag = false;
            actionBuffer = await ReadFromStreamAsync();
            while (!flag)
            {
                byte type = actionBuffer[0];
                int value = 0;
                if (type > 0)
                {
                    byte[] valueBytes = { actionBuffer[4], actionBuffer[3], actionBuffer[2], actionBuffer[1] };
                    value = BitConverter.ToInt32(valueBytes, 0);
                    actionBuffer = actionBuffer.Skip(5).ToArray();
                    CommonVariables.RawMessages.Add(new KeyValuePair<byte, int>(type, value));
                    OnHandler();
                }
                else
                    flag = true;                     
            }    
        }
    }        
    byte[] buf = new byte[MAXVALUEPACKET];
    async Task<byte[]> ReadFromStreamAsync()
    {
        await s.ReadAsync(buf, 0, MAXVALUEPACKET);
        return buf; 
    }

【问题讨论】:

  • ReadAsync: "TResult 参数的值包含读入缓冲区的总字节数。结果值可以小于请求的字节数,如果当前可用字节数小于请求数"
  • 而且,最重要的是,TCP 抽象是字节流。不能保证每次调用Send 都会与另一端调用Receive 1-1 匹配。如果您想要“数据包”或“消息”,则由在 TCP 上实现帧逻辑,或移至更高级别的抽象。
  • @Damien_The_Unbeliever 是的,谢谢!只读5个字节,已经好多了!

标签: c# asynchronous networking


【解决方案1】:

MAXVALUEPACKET = 5 设置为每 5 个字节读取一次可能有助于避免字节丢失:

        const int MAXVALUEPACKET = 5;
        async Task process()
        {
            while (true)
            {
                var actionBuffer = await ReadFromStreamAsync();
                byte type = actionBuffer[0];
                int value = 0;
                if (type > 0)
                {
                    byte[] valueBytes = { actionBuffer[4], actionBuffer[3], actionBuffer[2], actionBuffer[1] };
                    value = BitConverter.ToInt32(valueBytes, 0);
                    CommonVariables.RawMessages.Add(new KeyValuePair<byte, int>(type, value));
                    OnHandler();
                }
            }
        }

        async Task<byte[]> ReadFromStreamAsync()
        {
            await s.ReadAsync(buf, 0, MAXVALUEPACKET);
            return buf;
        }

原代码逻辑的问题是当迭代到第820个循环时,还剩下1个字节,导致读取整数值的逻辑失败。我假设服务器总是在每个部分中写入 5 个字节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 2011-10-09
    • 1970-01-01
    • 2019-07-04
    相关资源
    最近更新 更多