2012-02-02 30 views
11

是否有可能检测一个原始协议缓冲消息的类型(在字节[])协议缓冲器从原料消息检测类型

我有一个情况,端点可以接收不同的消息和我需要能够在我可以反序列化之前检测类型。

我使用protobuf网

+0

我只是使用多个端点。函数重载在编程语言中足够笨重,在网络服务中则少得多。 – millimoose 2012-02-02 23:32:25

+0

谢谢,这是我的备份计划:) – 2012-02-02 23:34:33

回答

14

您无法单独检测类型,因为protobuf规范不会将任何数据添加到此流;但是,也有一些使这个容易,这取决于上下文的方法:

  • (如由Jon提到的)联合类型涉及一系列场景
  • 继承(protobuf网专用)可以是多才多艺的 - 你可以有一个基本的消息类型,以及任意数量的具体信息类型的
  • 您可以使用前缀指示输入型

最后的方法实际上是在原TCP的情况下非常有价值流;这是的网线与联合类型相同,但具有不同的实现;通过预先确定1 = Foo,2 = Bar等(与联合类型方法完全相同),可以使用SerializeWithLengthPrefix来编写(指定1/2/etc作为字段编号),以及非通用TryDeserializeWithLengthPrefix可以读取(这是在v1 API中的Serializer.NonGeneric下,或者在v2 API中的TypeModel中),您可以提供一个类型映射表,将数字解析为类型,然后反序列化正确的类型。并预先解决“为什么这对TCP流有用?”这个问题。 - 因为:在正在进行的TCP流中,您需要需要使用WithLengthPrefix方法总之,以避免过度读取流;所以你不妨获得免费的类型标识符!

摘要:

  • 联盟类型:易于实现;只有一边是不得不然后检查哪些属性是非空的
  • 继承:易于实施;可以使用多态性或鉴别器来处理“现在什么?”
  • 类型前缀:更繁琐一点来实现,但允许更大的灵活性,并具有零开销上的TCP流
+0

嗨,感谢您的详细回复。 我设法使用Serializer.SerializeWithLengthPrefix&Serializer.NonGeneric.TryDeserializeWithLengthPrefix 完成所需的结果我想使用RuntimeTypeModel来避免我的类有属性。 Model.SerializeWithLengthPrefix似乎按预期工作,但我无法在RuntimeTypeModel上找到TryDeserializeWithLengthPrefix的等价性。 model.DeserializeWithLengthPrefix似乎期待一种类型。我应该如何使用模型完成TryDeserializeWithLengthPrefix的等价物。 使用版本2.0.0.480 nuget – 2012-02-03 10:18:40

+0

我已更改我的代码以添加以将模型定义添加到RuntimeTypeModel.Default,并且我可以使用TryDeserializeWithLengthPrefix没有属性。在我使用TypeModel创建新模型之前创建 所以问题解决了谢谢 – 2012-02-03 11:11:13

+0

@Yavor on TypeModel,它只是DeserializeWithLengthPrefix和TypeResolver。不确定尝试去了哪里!我会在沙发上的垫子后面寻找它 - 这是大多数情况下的结果。 – 2012-02-03 13:51:20

12

一个典型的选择是有包装的消息充当“选项类型”或可识别联合。您可以拥有一个枚举(每个消息类型一个)和一个包含消息类型字段的消息,然后每个消息类型都有一个可选字段。

这在Protobuf文档中描述为"union type"

3

你可以把它包像这样。数据将保存实际的消息。

message MyCustomProtocol { 
    required int32 protocolVersion = 1; 
    required int32 messageType = 2; 
    bytes data = 3; 
} 

协议的一般规则是包含协议版本。一旦你有新老客户,你会很高兴拥有它。

相关问题