應(yīng)用層協(xié)議設(shè)計(jì)

協(xié)議

  • 什么是協(xié)議:協(xié)議是一種約定,通過(guò)約定,不同的進(jìn)程可以對(duì)一段數(shù)據(jù)產(chǎn)生相同的理解,可相互協(xié)作。進(jìn)程間的通信一定需要協(xié)議。
  • \color{rgb(255,0,0)} {為什么說(shuō)進(jìn)程間通信就需要協(xié)議?}
  • \color{rgb(255,0,0)} {為什么需要自己設(shè)計(jì)協(xié)議?}

協(xié)議設(shè)計(jì)目標(biāo)

  • 解析效率:互聯(lián)網(wǎng)業(yè)務(wù)具有高并發(fā)的特點(diǎn),解析效率決定了使用協(xié)議的CPU成本
  • 編碼長(zhǎng)度:信息編碼后的長(zhǎng)度,編碼長(zhǎng)度決定了使用協(xié)議的網(wǎng)絡(luò)帶寬及存儲(chǔ)成本
  • 易于實(shí)現(xiàn):互聯(lián)網(wǎng)業(yè)務(wù)需要輕量級(jí)的協(xié)議,而不是大而全
  • 可讀性:編碼后的數(shù)據(jù)的可讀性決定了使用協(xié)議的調(diào)試及維護(hù)成本(某些情況下需要可讀性)
  • 兼容性:互聯(lián)網(wǎng)的需求具有靈活多變的特點(diǎn),協(xié)議會(huì)經(jīng)常升級(jí),使用協(xié)議的雙方是否可以獨(dú)立升級(jí)協(xié)議、增減協(xié)議中的字段是非常重要的
  • 跨平臺(tái)跨語(yǔ)言:互聯(lián)網(wǎng)的業(yè)務(wù)涉及到不同的平臺(tái)和語(yǔ)言
  • 安全可靠:防止數(shù)據(jù)被破解

協(xié)議設(shè)計(jì)最核心解決的問(wèn)題

1、序列化/反序列化
2、判斷包的完整性

協(xié)議設(shè)計(jì)進(jìn)階問(wèn)題

3、協(xié)議升級(jí)
4、協(xié)議安全
5、數(shù)據(jù)壓縮

序列化/反序列化

什么是序列化和反序列化?

  • 序列化:把對(duì)象轉(zhuǎn)換為字節(jié)序列的過(guò)程稱為對(duì)象的序列化
  • 反序列化:把字節(jié)序列恢復(fù)為對(duì)象的過(guò)程稱為對(duì)象的反序列化
    協(xié)議.png

序列化方法

  • TLV編碼及其變體(TLV是tag, length和value的縮寫):比如protobuf
  • 文本流編碼:比如xml json
  • 固定結(jié)構(gòu)編碼:協(xié)議約定了傳輸字段類型和字段含義,和TLV的方式類似,但是沒(méi)有了tag和length,只有value,比如tcp
  • 內(nèi)存dump:把內(nèi)存中的數(shù)據(jù)直接輸出,不做任何序列化操作。反序列化的時(shí)候,直接還原內(nèi)存(不建議在互聯(lián)網(wǎng)使用,在嵌入式方面可以使用)

主流序列化協(xié)議

主流序列化協(xié)議:xml、json、protobuf

  • xml 指可擴(kuò)展標(biāo)記語(yǔ)言(eXtensible Markup Language)。是一種通用和重量級(jí)的數(shù)據(jù)交換格式,以文本方式存儲(chǔ)
  • json (JavaScript Object Notation,JS 對(duì)象簡(jiǎn)譜) 是一種通用和輕量級(jí)的數(shù)據(jù)交換格式,以文本結(jié)構(gòu)進(jìn)行存儲(chǔ)
  • protocol buffer是Google的一種獨(dú)立和輕量級(jí)的數(shù)據(jù)交換格式,以二進(jìn)制結(jié)構(gòu)進(jìn)行存儲(chǔ)。
類型 通用性 大小 格式
xml 通用 重量級(jí) 文本格式
json 通用 輕量級(jí) 文本格式(方便調(diào)試)
protobuf(編譯器,生成對(duì)應(yīng)語(yǔ)言的代碼) 獨(dú)立 輕量級(jí) 二進(jìn)制格式

判斷包的完整性

為了能讓對(duì)端知道如何給包分解,目前一般有以下做法:
1、以固定大小字節(jié)數(shù)來(lái)分界,如每個(gè)包100字節(jié),對(duì)端每收齊100個(gè)字節(jié),就當(dāng)成一個(gè)包來(lái)解析
2、以特定符號(hào)來(lái)分界,如每個(gè)包都以特定的字符來(lái)結(jié)尾(如\r\n),當(dāng)在字節(jié)流中國(guó)讀取到該字符時(shí),則表明上一個(gè)包到此為止
3、固定包頭+包體結(jié)構(gòu),這種結(jié)構(gòu)中一般包頭部分是一個(gè)固定字節(jié)長(zhǎng)度的結(jié)構(gòu),并且包頭中會(huì)有一個(gè)特定的字段指定包體的大小。收包時(shí),先接收固定字節(jié)數(shù)的頭部,解出這個(gè)包完整長(zhǎng)度,按此長(zhǎng)度接收包體。這是目前各種網(wǎng)絡(luò)應(yīng)用用的最多的一種包格式
4、在序列化后的buffer前面增加一個(gè)字符流的頭部,其中有個(gè)字段存儲(chǔ)包總長(zhǎng)度,根據(jù)特殊字符(比如\n或者\(yùn)0)判斷頭部的完整性。這樣通常比3要麻煩一些,http和redis采用的就是這種方式。收包的時(shí)候,先判斷已收到的數(shù)據(jù)中是否包含結(jié)束符,收到結(jié)束符后解析包頭,解出這個(gè)包完整長(zhǎng)度,按此長(zhǎng)度接收包體

協(xié)議設(shè)計(jì)參考范例

字段 類型 長(zhǎng)度(字節(jié)) 說(shuō)明
STAG unsigned short 2 通信協(xié)議數(shù)據(jù)包的開(kāi)始標(biāo)志
version unsigned short 2 通信協(xié)議的版本號(hào)
checksum unsigned char 1 計(jì)算協(xié)議數(shù)據(jù)校驗(yàn)和,如果為加密數(shù)據(jù),則計(jì)算密文校驗(yàn)和。校驗(yàn)和計(jì)算范圍:協(xié)議頭CheckSum字段后數(shù)據(jù),協(xié)議體全部數(shù)據(jù)。
type unsigned char 1 0表示協(xié)議體是json格式,其它值未定義。設(shè)備心跳消息類型的值為0xA0
seqno unsigned int 4 通信數(shù)據(jù)報(bào)文的序列號(hào),應(yīng)答報(bào)文序列號(hào)必須與請(qǐng)求報(bào)文序列號(hào)相同
length unsigned short 2 報(bào)文內(nèi)容長(zhǎng)度,即從該字段后報(bào)文內(nèi)容長(zhǎng)度
reserve unsigned int 4 預(yù)留字節(jié),設(shè)備心跳消息類型的值為devid

協(xié)議升級(jí)

1、通過(guò)版本號(hào)指明協(xié)議版本,即是通過(guò)版本號(hào)辨別不同類型的協(xié)議
2、支持協(xié)議頭部可擴(kuò)展,即是在設(shè)計(jì)協(xié)議頭部的時(shí)候有一個(gè)字段用來(lái)指明頭部的長(zhǎng)度

協(xié)議安全

1、xxtea 固定 key
2、AES 固定 key
3、openssl
4、signal protocol 端到端的通訊加密協(xié)議

數(shù)據(jù)壓縮

1、deflate
2、gzip
3、lzw


2021.8.20 17:28 深圳

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容