1. 程式人生 > >TLV-簡單的資料傳輸協議

TLV-簡單的資料傳輸協議

         有段時間沒有寫部落格了,這段期間要說也夠忙的(其實也沒忙到哪去),從3月底到5月初這段期間一直在找暑期實習,幸運的是自己算是找到了自己希望的,從開始糾結TX,到後來確定,以及又拿到阿里的實習機會,這段過程真是夠虐心的。不過自己還是選擇了深圳,也許是阿里巴巴的通知有點晚,也許是自己覺得毀約去杭州有點不好,也許是因為那個QQ空間上裝逼的我讓我做了這個感性的決定.不管怎樣,感謝阿里巴巴給的機會,也特別感謝六一、淘寶褚霸兩位阿里大牛沒有狠狠虐我。不多說,就以上做一個小結吧。(最近總是喜歡囉嗦)

         不扯淡,今天要說的便是TLV,即Tag(Type-Length-Value,是一中簡單實用的資料傳輸方案。在TLV

的定義中,可以知道它包括三個域,分別為:標籤域(Tag),長度域(Length),內容域(Value)。這裡的長度域的值實際上就是內容域的長度。

其實就是一個簡單的自定義通訊協議,將對應的資料進行編碼、組織。我們之前自己寫一個簡單的C/S模型資料傳輸時,比如傳送一個非基礎型別的結點資訊,就會採用struct,比如:

  struct Messagebase{
      unsigned int command;
      char login_code[8];
      char name[8];
  };

         這個struct描述了簡單的login操作的需求資訊,但是比如說有一天我們需要增加一個欄位,加上

login人的年齡,就需要新的一個欄位:

  struct Messagebase{
      unsigned int command;
      unsigned int birthday;
      char login_code[8];
      char name[8];
  };

        這樣導致的結果就是對應解析的程式碼也需要進行修改,加入針對birthday欄位的處理,因為原先的處理不知道資料包的第三個欄位是name還是login_code,這樣的處理只能用作簡單的資料包擴充套件。

        但是這個擴充套件有很大的侷限性,總不能這麼一直修改吧,所以考慮可以給每個資料段加上一個表示Tag

Type),這樣就不用擔心欄位的任意添加了,並且對於name域來說,定長的特性肯定是不行的,所以,所以,就有了<Tag, Length, Value>三元組編碼,簡稱TLV編碼。但是需要注意的是,Value具體的含義,還是需要通訊需求來決定,所以用裝逼的話來說,TLV這種編碼方式不具備結構化(結構未知)特點。但是TLV具備很好的擴充套件性,其中欄位可以是結構式巢狀即value 域支援複合型元資料結構,比如如下定義:

  struct tlv_entity {
      unsigned char* tag;        //標記
      unsigned char* length;     //資料長度
      unsigned char* value;      //資料
      unsigned int tagSize;      //標記佔用位元組數
      unsigned int lengthSize;   //資料長度佔用位元組數
      tlv_entity* sub_tlventity;  //子巢狀TLV實體
  };

         資料的傳送過程其實就是打包的過程,目的是將一個從終端上發的請求資料——位元組陣列,構造成一系列的TLV結構實體;解包的目的剛好相反,就是將TLV結構實體解析成位元組陣列,所以對應我們需要一個針對TLV資料的封裝處理:

  class tlv_deal{
      Public:
      tlv_deal();
      virtual ~tlv_deal();
      static void construct_MS(unsigned char* buffer,unsigned int buffer_len,
          tlv_entity* entity,unsigned int entity_len,unsigned int status=0 );
      static void parse_MS(unsigned char* buffer,unsigned int buffer_len,
          tlv_entity* entity,unsigned int entity_len);
  };

        對於簡單的TLV資料元結構,盜圖如下:

       
        複合的TLV資料元結構:

          

          Primitive or constructed BER-TLV data object number,包含一個簡單資料元結構或者也可以是一個符合資料元結構。這樣可以看出,演算法中必須要實現Tag的巢狀功 能,遞迴演算法不可少。

         其實說白了,我們看到的XML等標記式的結構也是屬於TLV的,以及facebookthrift,還有googleprotobuf (在這說純屬裝逼,只是簡單瞭解),基本都是TLV的例子,但是模型簡單,實際的需求決定了處理的難度。哎,就算是簡單的概念吧,我估計大家都沒發覺自己以前寫程式碼用了這樣的概念,只是不知道名字罷了,但是真正的一個巢狀式的TLV結構,在實際應用中絕對還是不簡單的,打包、解析也絕對會是體力活。額,都不知道說什麼了,還是去再看看對應的應用層協議設計再來裝逼吧。