2012-02-02 31 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; 
} 

協議的一般規則是包含協議版本。一旦你有新老客戶,你會很高興擁有它。

相關問題