C語言與物聯網之簡單通信協議
用C語言做物聯網網關開發時,經常需要通過串口、485接口等從一些傳感器讀取數據,由于網關設備和傳感器所處的環境復雜多樣,電磁干擾等常常會破壞傳輸的數據,為了確保傳輸數據的可靠性,通常會采取一些策略,常用的策略:數據校驗+超時重傳,具體過程如下:
發送方在發送數據時,在元數據的基礎上增加校驗數據形成請求數據包(data pack),然后將請求數據包發送出去,并啟動守衛計時器(Guard Timer)。
接收方在收到請求數據包后,以跟發送方相同的算法對元數據進行計算得到校驗數據,然后跟收到的校驗數據進行比較,若相同,則說明數據可靠,可以使用;反之,說明數據被破壞,直接丟棄掉。若數據可靠,接收方以同樣的格式做成響應數據包回復給發送方;若發現數據被破壞,接收方不回復任何數據。
如果發送方在守衛計時器超時前正確地接收到了接收方回復的響應數據包,則停止守衛計時器,并進行后續的處理;若發送方在守衛計時器超時時仍未收到接收方回復的響應數據包,則重新發送"1."中的數據包,如此反復,直到正確發送或達到了重傳次數。
步驟1~3重點為了講述如何確保數據可靠傳輸,真實情景中為了能正確地斷包(識別數據包),通常會按照如下結構來定義數據包:

- 包起始標識:通常使用固定數據,比如0xFA, 0xAA, 0xA5等;
- 元數據長度:根據元數據長度進行斷包。比如:元數據長度占1字節,校驗數據占2字節,當元數據長度取值為10時,則數據包大小為14字節;
- 元數據:發送的或接收的,有一定格式或意義的應用數據;
校驗數據:按照某種校驗算法(比如checksum,crc等)計算得到的值。
- #define MAX_DATA_LEN 100 /* 假設元數據的最大長度為100字節 */
- typedef struct tag_data_pack {
- uint8_t sop; /* 包起始標識,(Start Of Pack) */
- uint8_t len; /* 元數據長度,假設為1字節 */
- uint8_t datas[MAX_DATA_LEN + 2]; /* 元數據 + 2字節的校驗數據 */
- }data_pack_t;
總線式的通信中,通常還會在數據包中加入目標設備的地址,以便于確定數據是發往總線上的哪個設備,數據包的參考結構如下:

用C語言描述如下:
- #define MAX_DATA_LEN 100 /* 假設元數據的最大長度為100字節 */
- typedef struct tag_data_pack {
- uint8_t sop; /* 包起始標識,(Start Of Pack) */
- uint8_t addr; /* 目標設備地址,假設為1字節 */
- uint8_t len; /* 元數據長度,假設為1字節 */
- uint8_t datas[MAX_DATA_LEN + 2]; /* 元數據 + 2字節的校驗數據 */
- }data_pack_t;