6

使用 Google 协议缓冲区,我可以为我编码的所有消息设置最大大小吗?

如果我知道我编码的内容永远不会大于 X 字节,那么 Google Protobuffs 将始终生成大小为 Y 的缓冲区,如果我给它提供的数据量较少,则将其填充为大小 Y?

4

1 回答 1

5

协议缓冲区的有线格式不会让这变得微不足道。我不知道有什么办法可以做到这一点,但一种选择是将它序列化到一个带有你自己的长度标头的缓冲区中,并根据需要用额外的数据填充。

您需要添加一个长度前缀,因为默认情况下不会添加它,否则它将在缓冲区末尾读取垃圾。即使尾随 0 也不合法(它会寻找字段编号)。

我无法评论 C++ 或 Jon 的 C# 版本,但对于我的C# 版本(protobuf-net),您应该能够执行以下操作(未经测试):

using(var  ms = new MemoryStream(fixedLength)) {
     ms.SetLength(fixedLength);
     Serializer.SerializeWithLengthPrefix(ms, obj);
     if(ms.Length > fixedLength) { /* boom */ }
     byte[] arr = ms.ToArray(); // use this
}

如果还使用DeserializeWithLengthPrefix.


重新提出问题(评论);SerializeWithLengthPrefix是一种protobuf-net特有的方法;C++ 版本中可能有一些东西,但它非常简单。从头开始实现此功能的最简单方法是:

  • 假设我们将留下一个固定长度(4 字节)的标头来指示我们有多少实际数据
  • 跳过 4 个字节(或写入 00-00-00-00)
  • 现在序列化到缓冲区的其余部分
  • 找出你刚刚写了多少字节
  • 在缓冲区的开头写回该值

相反,显然:

  • 读取 4 个字节并解释为 int
  • 反序列化和数据一样多

它在 protobuf-net 中稍微复杂一些,因为它提供了更多选项(应该如何对 int 进行编码,以及是否包装它以便整个事物仍然可以被视为 100% 值的 protobuf 流- 特别是我怀疑我刚刚描述了如果我要求SerializeWithLengthPrefix使用固定宽度编码和“字段0”的行为)。

于 2010-05-12T08:22:37.547 回答