【问题标题】:Protobuf-net sirialization/deserialization c# vs Linux c++Protobuf-net 序列化/反序列化 c# vs Linux c++
【发布时间】:2014-12-30 21:10:42
【问题描述】:

我正在通过 TCP 套接字在 Windows C# 客户端和 Linux C++ 服务器之间传递消息。 C# 代码使用 protobuf-net v2,Linux Google 的 protobuf 版本。我通过的小测试对象有 6 个字段(枚举、整数、字符串)。我需要帮助解决两个问题:

  1. C# 部分无法反序列化从 Linux 发送的数据,除非用作数据存储的内存流在构造函数中使用二进制数组进行了初始化。数组不能大于从 Linux 发送的数据(在我的例子中是 9 个字节)。代码示例 - byte[] data = new byte[9],将数据从套接字复制到数组中。 MemoryStream myStream = new MemoryStream(data),将 myStream 传递给 Serializer.Deserialize... 如果我在没有二进制缓冲区或 1024 字节数组的情况下初始化 MemoryStream,则反序列化将创建空对象,而不处理数据。

  2. 当我尝试在 C# 中使用与 Linux 相同的值序列化相同的对象时,数据大小为 11 字节,而 Linux 为 9。我在调试器中检查了字节数组,C# 版本在数组的索引 2-11 中具有与 Linux 数据相同的 9 个字段。索引 0 是 8,索引 1 是 9。我可以尝试通过修改 Linux 反序列化代码来解决这个问题,只需要知道,我是否总是必须处理消息开头的两个额外字段。另外,如果要修复我在 C# 中的反序列化,我可以在 Linux 上生成的消息中添加两个额外的字段,只需要知道如何为这两个字段生成值。

谢谢。 亚历克斯。

【问题讨论】:

  • 嗨@Marc。感谢您的及时回复。我能够确定 C++ 和 C# 数据之间差异的来源。 C++ 没有使用默认值填充枚举字段。我更关心 C# 中的反序列化。我打算用预分配的缓冲区重用相同的流,但它不起作用。现在我必须分配新的字节数组以匹配消息中数据的大小,并将其传递给 MemoryStream 构造。我预计消息率很高,我描述的解决方案将导致频繁的垃圾收集。我可以重复使用 ProtoReader 以避免额外分配吗?

标签: c# c++ linux serialization protobuf-net


【解决方案1】:
  1. 简单来说,Protobuf 数据不会自行终止。但是,您可以创建一个MemoryStreamProtoReader,它占用 更大的有效负载,但限制为虚拟长度。如果您要发送多条消息,您将需要知道有效负载的长度——这是不可避免的。这通常通过长度前缀来实现。我希望这会引发随机错误——很可能是“无效的字段标题 0”——我想知道你是否正在吞下那个异常
  2. 没有具体的例子就无法评论;很可能与字段编号 1 的默认值有关(标题 8 === "field 1 varint")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多