为什么我的protobuf网络流不起作用

本文关键字:不起作用 网络 protobuf 我的 为什么 | 更新日期: 2023-09-27 18:37:10

我有一个可以序列化和反序列化的对象,但在反序列化时它抛出了一个错误:

Invalid field in source data: 0

我不知道为什么会这样

用于反序列化和接收的代码:

public void listenUDP()
{
        EndPoint ep = (EndPoint)groupEP;
        //BinaryFormatter bf = new BinaryFormatter();
        recieving_socket.Bind(ep);
        while (true)
        {
            byte[] objData = new byte[65535];
            recieving_socket.ReceiveFrom(objData, ref ep);
            MemoryStream ms = new MemoryStream();
            ms.Write(objData, 0, objData.Length);
            ms.Seek(0, SeekOrigin.Begin);
            messageHandle(ProtoBuf.Serializer.Deserialize<SimplePacket>(ms));
            ms.Dispose();

        }
    }

序列化代码:

public void sendDataUDP(Vec2f[] data)
    {
            SimplePacket packet = new SimplePacket(DateTime.UtcNow, data);
            //IFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            System.Diagnostics.Stopwatch st = System.Diagnostics.Stopwatch.StartNew();
            //formatter.Serialize(stream, data);
            ProtoBuf.Serializer.Serialize<SimplePacket>(stream, packet);
            //Console.WriteLine(st.ElapsedTicks);
            stream.Close();
            st.Restart();
            sending_socket.SendTo(stream.ToArray(), sending_end_point);
            //Console.WriteLine(st.ElapsedTicks);
            st.Stop();
    }

为什么我的protobuf网络流不起作用

protobuf 消息中的根对象,由 google 规范定义,不包含消息结尾的任何概念。这是有意为之,因此串联与合并两个片段相同。因此,使用代码需要将自身限制为单个消息。这在所有 protobuf 实现之间是相同的,并且不是特定于 protobuf-net 的。

正在发生的事情是,您的缓冲区当前过大,末尾有垃圾。目前(因为您正在阅读一条消息)垃圾很可能都是零,零不是字段的有效标记。但是,当重复使用缓冲区时,垃圾可能是...什么。

在您的情况下,最简单的方法可能是使用 SerializeWithLengthPrefix/DeserializeWithLengthPrefix 方法,该方法通过在消息开头预置有效负载长度并仅处理那么多数据来为您处理所有这些。

作为最后一个想法:我不清楚你的代码是否会保证已经读取了整个消息;单个接收可以(至少在TCP上)返回消息的一部分 - 或2和1位消息等:TCP是基于流的,而不是基于消息的。