读取具有 UTF8 编码的 NetworkStream

Read NetworkStream with UTF8 Encoding

提问人:Martin Wiklund 提问时间:11/3/2023 最后编辑:Martin Wiklund 更新时间:11/5/2023 访问量:26

问:

我正在尝试通过网络流发送JSON对象。我能够发送一条消息并反序列化它,但在接收它后,我的 While 循环退出。我认为这与 NetworkStream.Read 期望固定字节大小编码 (ASCII) 有关,但我使用的是具有不同字节大小的 UTF8。 有没有办法让NetworkStream.Read读取正确的字节数?

发送数据的功能:

        private void SendMessage(TcpClient client, string message)
    {
            stream = client.GetStream();

            var data = new MessageModel
            {
                RequestType = "Message",
                Name = clientName,
                Date = DateTime.Now,
                Message = message
            };

            string jsonString = JsonSerializer.Serialize(data);
            byte[] jsonData = UTF8Encoding.UTF8.GetBytes(jsonString);
            stream.Write(jsonData, 0, jsonData.Length);
        }
    }

接收数据的功能:

    private void RecieveMessages(TcpClient client)
    {
        NetworkStream stream = client.GetStream();

        byte[] data = new byte[1024];
        int bytesRead;

        while ((bytesRead = stream.Read(data, 0, data.Length)) > 0)
        {
            string jsonString = UTF8Encoding.UTF8.GetString(data, 0, bytesRead);
            MessageModel message = JsonSerializer.Deserialize<MessageModel>(jsonString);

            Console.WriteLine($"RequestType: {message?.RequestType}");
            Console.WriteLine($"Name: {message?.Name}");
            Console.WriteLine($"Date: {message?.Date}");
            Console.WriteLine($"Message: {message?.Message}");
        }

        client.Close();
        Console.WriteLine("Client disconnected.");
    }

解决:正如 Jon Skeet 所指出的,这与编码无关。我在写消息时不小心关闭了客户端流。

C# 字符编码 缓冲区 NetworkStream

评论

1赞 Jon Skeet 11/3/2023
“我认为这与NetworkStream.Read期望固定字节大小编码(ASCII)有关”——是什么让你得出这个结论?听起来写入端已经关闭了流,否则不会返回 0。(请注意,假设您将在一次阅读中获得完整的消息真的很危险......有多种方法可以将流用于离散消息,例如“在关闭流之前使用一条消息”,或长度前缀,或分隔符(例如换行符),否则永远不会出现。stream.Read
0赞 Martin Wiklund 11/3/2023
你是对的,与具有不同字节大小的 UTF8 无关,我在写完后不小心关闭了连接。谢谢!
0赞 Charlieface 11/3/2023
旁注:你的阅读逻辑有一个致命的缺陷。不能保证另一方的一次发送将导致一次接收。它们可以拆分或加入到多个数据包或缓冲区中。您需要一个消息框架协议,请参阅 blog.stephencleary.com/2009/04/message-framing.html 考虑使用现有协议(如 HTTP),而不是滚动自己的协议。

答: 暂无答案