我目前正在评估在项目中使用的协议缓冲区(目前还没有编写代码)。我不清楚的一件事是您将如何阅读编码消息的一部分,例如说我有一个共同的标头:
message Header {
required uint16 msg_type = 1;
required uint16 length = 2;
}
假设我将多个不同的消息传递到一个队列。消费者如何计算出每条消息要读取多少数据以及应该构造什么消息类型?
我目前正在评估在项目中使用的协议缓冲区(目前还没有编写代码)。我不清楚的一件事是您将如何阅读编码消息的一部分,例如说我有一个共同的标头:
message Header {
required uint16 msg_type = 1;
required uint16 length = 2;
}
假设我将多个不同的消息传递到一个队列。消费者如何计算出每条消息要读取多少数据以及应该构造什么消息类型?
这里应该不需要Header
留言;最常见的方法是遵循此处的“流式传输”建议。在其中,您可以将其视为一系列相同的联合类型消息,或者(我的偏好)在编写时,而不是在每个之前写一个长度前缀,包括一个指示消息类型的 varint,然后是长度(作为变体)。指示消息类型的数字是您发明的任意映射,因此 1 = Foo、2 = Bar、3 = Blap 等)。如果您将消息类型左移 3 位然后“或”2,那么它本身也将是一个格式良好的 protobuf 流,与 100% 相同repeated YourUnionType
。
基本上,这与此 answer完全相同,但不是每次都是字段 1,而是每个消息类型的数字都不同。大多数实现都有一个读取器/写入器 API,可以读取和写入原始变量,并限制读取器 API 的长度。一些实现具有帮助机制来直接支持异构消息流(基本上,为您完成上述所有工作)。
在最近的一个项目中,我使用了这样的协议缓冲区:
我们有一个“容器”消息,其中包含所有实际消息作为可选成员:
message ContainerMessage {
optional Message1 message_1 = 1;
optional Message2 message_2 = 2;
//...
optional MessageN message_N = N;
}
在应用程序中,您可以将ContainerMessage
其用作真实消息的有区别的联合。
Between applications, we serialized/deserialized the ContainerMessage
and sent the serialized content, prefixed with a simple header containing the length of the serialized content.
这将取决于您使用的协议。
请注意,例如,许多协议通过串行接口进行,在那里您可能有额外的行来告诉消息何时开始和停止。
通常,消息将在消息开始后具有固定偏移量的长度。
在其他情况下,您可能需要逐个元素地解析消息元素以找出剩余的消息量。所以嵌入在消息中的字符串可能是固定长度的,或者在开头有长度,或者可能有 \0 作为结束标记。
大多数情况下,当您将消息存储在队列中以进行进一步处理时,您将希望添加更多信息以使您的生活更轻松 - 例如,当您只有一个额外的信号告诉您消息何时停止时,您可能会在内部存储消息及其长度。