协议缓冲区 - 读取所有消息中共同的标头(嵌套消息)

时间:2012-11-13 14:41:07

标签: c++ protocol-buffers

我目前正在评估在项目中使用的协议缓冲区(目前还没有编写代码)。我不清楚的一件事是你如何读取编码信息的一部分,例如说我有一个共同的标题:

message Header {
  required uint16 msg_type = 1;
  required uint16 length = 2;
}

并说我将多个不同的消息发送到队列。消费者如何计算出每条消息要读取多少数据以及应该构造哪种消息类型?

3 个答案:

答案 0 :(得分:4)

这里不应该有Header消息;最常见的方法是遵循“流式”建议from here。在其中,您可以将其视为一系列相同的union type消息,或者(我的偏好)在写入时,而不是仅在每个消息之前写入长度前缀,包括指示消息类型的varint然后长度(作为varint)。指示消息类型的数字是您发明的某个任意映射,因此1 = Foo,2 = Bar,3 = Blap等)。如果你将消息类型左移3位然后“或”2,那么它也将是一个格式正确的protobuf流本身,与repeated YourUnionType 100%相同。< / p>

基本上,这与this answer完全相同,但每次都不是字段1,而是每个消息类型的数量不同。大多数实现都有一个读取器/写入器API,可以读取和写入原始varint,并限制读取器API。一些实现具有帮助机制来直接支持异构消息流(基本上,为您完成上述所有操作)。

答案 1 :(得分:2)

在最近的一个项目中,我使用了像这样的Protocol Buffers:

我们有一条“容器”消息,其中包含所有实际消息作为可选成员:

message ContainerMessage {
    optional Message1 message_1 = 1;
    optional Message2 message_2 = 2;
    //...
    optional MessageN message_N = N;
}

在应用程序中,您可以使用ContainerMessage作为真实消息的区别联合。

在应用程序之间,我们序列化/反序列化ContainerMessage并发送序列化内容,前缀为包含序列化内容长度的简单标题。

答案 2 :(得分:0)

这取决于您使用的协议。

请注意,例如很多协议都是通过串行接口进行的,你可能会有额外的线路告诉消息何时开始和停止。

通常,消息在消息开始后将在固定偏移量处具有长度。

在其他情况下,您可能需要逐个元素地解析消息,以找出剩余的消息量。因此,消息中嵌入的字符串可能具有固定长度,或者在开头具有长度,或者可能具有\ 0作为结束标记。

大多数情况下,当您将消息存储在队列中以进行进一步处理时,您需要添加更多信息以使您的生活更轻松 - 例如当您只是有一个额外的信号告诉您消息何时停止时,您可能会存储消息内部的长度。