2012-11-13 134 views
7

我目前正在評估在項目中使用的協議緩衝區(迄今尚未編寫代碼)。其中一個我對不清楚的事情是你如何將讀出的編碼信息的一部分,例如說我有一個共同的標題:協議緩衝區 - 讀所有消息的公共消息頭(嵌套消息)

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

而且說我提供多種不同的消息隊列。消費者將如何計算每條消息要讀取多少數據以及應構建哪種消息類型?

+0

我沒有幫忙,但我學到了很多 - thx的問題 – Caribou

回答

4

應該沒有必要在這裏輸入Header消息;最常見的方法是遵循「流媒體」建議from here。在這種情況下,您可以將其作爲一系列相同的union type消息或(我的首選)寫入,而不是僅在每個消息之前寫入長度前綴,包括一個varint,指示消息類型,然後是的長度varint)。指示消息類型的數字是您創建的某個任意地圖,所以1 = Foo,2 = Bar,3 = Blap等)。如果將消息類型左移3位然後「或」2,則它也將是格式良好的protobuf流,與repeated YourUnionType完全相同。

基本上,這與this answer完全一樣,但是每次都不是字段1,每個消息類型的數字都不相同。大多數實現具有讀/寫器API,可以讀取和寫入原始varints,並對讀取器API進行長度限制。一些實現具有幫助器機制來直接支持異構消息流(基本上,爲你做上述所有事情)。

+0

我看過工會的東西,看起來不錯,我需要的東西。爲了確保我得到了正確的結果,解決方案將有一個'包裝'類,它包含'required uint16 msg_type','required uint16 msg_len'和一組'optional'消息聲明。那麼我可以將所有消息定義爲單獨的消息,而不必考慮長度和類型? – Graeme

+0

@Graeme完全取決於你的意思; p是的,一個帶有「重複」(某種聯合類型)的包裝可以很好地工作,但最好的做法是像Bart的答案中那樣重複「ContainerMessage」。我無法想象當msg_type和msg_len有用時的情況,因爲這基本上已經處理過了 –

+0

謝謝Marc,非常有幫助,非常感謝。 – Graeme

0

這將取決於您使用的協議。

請注意,例如,許多協議都是通過串行接口進行傳輸的,在這些接口中,您可能會有額外的線路來告知消息何時啓動和停止。

通常情況下,消息開始後,消息的長度將固定在一個偏移量處。

在其他情況下,您可能需要逐個解析消息元素以查明消息的剩餘量。因此嵌入到消息中的字符串可以是固定長度的,或者在開始處具有長度,或者可以具有\ 0作爲結束標記。

大多數情況下,當您將消息存儲在隊列中進行進一步處理時,您需要添加更多信息以使您的生活更輕鬆 - 就像當您只有一個額外的信號告訴您消息何時停止一樣時,您可以存儲消息內部與其長度。

+0

protobuf是一個明確定義的單一協議,但是......這個答案是專門針對protobuf的嗎?或者這是在談論一般情況? –

+0

@Zane - 我想他是在談論https://developers.google.com/protocol-buffers/docs/faq – Caribou

+0

@Caribou:是的,抱歉沒有得到。謝謝你告訴我。 – Zane

2

在最近的一個項目,我用Protocol Buffers的是這樣的:

我們有一個「容器」的消息,其中包括所有的實際信息的可選成員:

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

中的應用程序,你可以只需使用ContainerMessage作爲真實消息的區分聯合。

在應用程序之間,我們對ContainerMessage進行了序列化/反序列化,併發送了序列化的內容,其前綴爲一個包含序列化內容長度的簡單頭文件。

相關問題