在外部消息中包括预编码的协议缓冲区消息
Include pre-encoded protocol buffer message within outer message
有没有一种方法可以在C++中创建一个包含预编码内部消息的协议缓冲区消息,而无需解析然后重新序列化内部消息?
为了澄清,请考虑以下消息定义:
message Inner {
required int i = 1;
// ... more fields ...
}
message Outer {
repeated Inner inners = 1;
// ... more fields ...
}
假设您有一个10字节数组的集合,每个数组都包含一个内部的编码版本。您想要创建一个包含10 Inners的Outer。您不想手动编码,因为Outer有其他字段,并且可能本身包含在其他消息中。有没有一种方法可以让协议缓冲区直接复制预编码的内部?
没有干净的方法,但有一些技巧性的方法。一种是定义这样的第二条消息:
message RawOuter {
repeated bytes inners = 1;
// ... same fields as Outer ...
}
除了inners
重复字段已从类型Inner
变为类型bytes
之外,RawOuter
与Outer
相同。如果使用Inner
的编码实例填充inners
,然后序列化RawOuter
,则会得到与使用解析的verison构建Outer
完全相同的结果。也就是说,嵌套消息的有线格式与包含该嵌套消息的序列化的bytes
字段的有线格式相同。这是protobuf编码的一个有趣的可利用的怪癖。
不过,这次黑客攻击有一些问题。特别是,如果您试图构建一个嵌入在其他proto中的Outer
实例,那么它不会很好地工作,因为您可能不想维护每个包含消息的两个副本,一个使用Outer
,另一个使用RawOuter
。
另一个更为棘手的选项是将编码的消息注入到Outer
实例的UnknownFieldSet
中。
Outer outer;
for (auto& inner: inners) {
outer.mutable_unknown_fields()
->AddLengthDelimited(1, inner);
}
UnknownFieldSet
用于存储解析时看到的与.proto
文件中定义的任何已知字段号不匹配的字段。其想法是,这允许您编写一个代理服务器,只需接收消息并将其转发到另一个服务器,而无需每次向协议添加新字段时重新编译代理。在这里,我们通过在其中粘贴一个值来滥用它,该值实际上对应于已知的字段,但实现不会注意到,因此它会很好地写出这些字段。
这种方法的主要问题是,如果其他人同时检查您的Outer
实例,他们会觉得inners
列表是空的,因为这些值实际上隐藏在其他地方。这是一个非常丑陋的黑客攻击,以后可能会再次困扰你。只有当您测量了性能差异并发现差异很大时,我才会推荐它。
还要注意,序列化代码总是最后写入未知字段,而已知字段是按字段号顺序写入的。解析器应该接受任何顺序,但偶尔你会发现有人将未解析的数据用作哈希映射键或其他东西,如果字段被重新排序,这种情况就会完全崩溃。
顺便说一句,您可以通过将字符串交换到适当位置而不是复制来提高这两种方法的性能,即
raw_outer->add_inners()->swap(inner);
或
outer->mutable_unknown_fields()->AddLengthDelimited(1)->swap(inner);
- 协议缓冲区ParseFromString不检查消息结尾
- 提升 ASIO 在基于 TCP 的协议中查找消息的开头
- 协议缓冲区#3将消息从c ++发送到c#
- Steam协议C 解压缩多消息
- Tcp 协议前缀消息的长度
- 将二进制数据缓冲区存储在协议缓冲区消息中
- 如何将多个协议缓冲区的消息写入可附加的压缩文件中?
- C++中的Google协议缓冲区:从现有结构中创建消息
- 协议缓冲区-读取所有消息中通用的标头(嵌套消息)
- Arduino不支持使用websocket协议发送超过65535个字符的消息
- 用于使用 istream/ostream 传输消息的类似网络协议
- 在调试模式下销毁协议缓冲区消息几乎比在发布模式下慢 500 倍
- 如何在mavlink协议中添加新消息
- 协议缓冲cpp嵌入的消息
- 如何将 boost::asio 用于没有标头告诉我消息大小的 TCP 协议?
- 在外部消息中包括预编码的协议缓冲区消息
- 如何在协议缓冲区中设置嵌套消息的字段
- 是否可以使用 Varint32 大小前缀的协议缓冲区消息实现类似"FileInputStream::BackUp()"的功能?
- 协议和非阻塞消息发送/接收
- 如何在协议缓冲区c++教程中编写消息