手寫協議報文 c語言手法

鑑於絕大部分文件、網絡通信協議、非網絡通信協議都有類似的結構{類型,長度,校驗,不定長數據,結束標誌},再高級點的會包含多個單層TLV,甚至嵌套TLV,狀態機流轉標誌等等。所以編程語言上也需要採用一定的手法。

建立結構

結構體和聯合體

例如

//結構體對齊宏
#if defined(__GNUC__)
#define PACKED_STRUCT struct __attribute__((packed))
#endif
#include <stdint.h> //for uint8_t etc.

PACKED_STRUCT Frame {
          uint8_t     HEADER;
          uint8_t     ftype;
          uint16_t    len;
          PACKED_STRUCT Payload payload;
};

struct Data {
  union {
    PACKED_STRUCT Frame frame;
    uint8_t rawdata[];
  };
} data;

使用技巧

這樣就可以通過結構體成員名直接操作

  • 寫入:data.frame.ftype = 0x89 直接填充。
  • 讀取:通過 data.rawdata[i] 直接取到完整的二進制數據。(i表示第i個字節),可以通過 %02X 將該rawdata打印出來

調試/單元測試:可以搞個讀寫回環,保證數據正確後再接入實際功能代碼。

位域

//記得使用packed屬性告訴編譯器不要瞎優化我的結構體
struct __attribute__((packed))  DataBitm {
	uint8_t flag: 1;
	uint8_t type: 4;
	uint8_t len:  3;
	uint32_t data[];
}

冒號 :1代表該變量只佔用1bit。 例如上面代碼,type佔用了4bit。我們序列化/反序列化的時候就可以直接取到內存映射上的4bit,而無需做位運算。

序列化(serialization)在計算機科學的資料處理中,是指將數據結構或對象狀態轉換成可取用格式(例如存成文件,存於緩衝,或經由網絡中發送),以留待後續在相同或另一臺計算機環境中,能恢復原先狀態的過程。 依照序列化格式重新獲取字節的結果時,可以利用它來產生與原始對象相同語義的副本。反序列化就是它的逆過程。

統一類型

記住這個C99標準庫頭文件 #include <stdint.h>,裏面的類型 uint8_t到uint32_t足夠使用,在所有支持C99編譯器上均可使用,包括常見的單片機編譯平臺,不需要自己定義一些奇奇怪怪又不完全通用的什麼u8 u32 U32 UINT32這樣的類型。

需要注意大小端問題

這個過程需要注意CPU大小端問題,以下是一些轉換宏可以用

//大小端轉換,其實就是字節換位
#define BIG_TO_LITTLE_ENDIAN_16(x) ((uint16_t)((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8)))
#define BIG_TO_LITTLE_ENDIAN_32(x) ((uint32_t)((((x) & 0xFF000000) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | (((x) & 0x000000FF) << 24)))

C99特性 - 柔性數組

另外還可以使用柔性數組來做不定長的協議報文,關鍵詞: C99 柔性數組,但柔性數組只能用在結構體的尾部,所以如果有幀尾,一般不把幀尾放入結構體裏,而是在函數裏手動填充。

然後在填充報文的函數裏再做switch分支即可完成協議的子類解析。
複製報文數據到發送區的時候一般使用 memcpy(dst,src,size);

狀態機流轉

最好畫一個狀態機的圖便於分析和修改,這個有很多畫流程圖的軟件都可以做到。

參考案例

接下來我們觀賞一段英特爾處理媒體流協議的代碼,是RTP協議下的子類。
GITHUB項目地址:https://github.com/OpenVisualCloud/Media-Transport-Library

數據填充

image

告訴編譯器不優化結構體

attribute ((packed)) 的作用就是告訴編譯器取消結構在編譯過程中的優化對齊,按照實際佔用字節數進行對齊,是GCC特有的語法。當然其他編譯器也有類似的屬性名

image

結構體和聯合體。

image

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章