系統(tǒng)設(shè)計(jì),協(xié)議先行。
大部分人不了解協(xié)議的設(shè)計(jì)細(xì)節(jié),更多使用已有協(xié)議進(jìn)行應(yīng)用層設(shè)計(jì),例如:
使用HTTP,設(shè)計(jì)get/post/cookie參數(shù),以及json包格式;使用dubbo,而不用去深究?jī)?nèi)部的二進(jìn)制包頭包體細(xì)節(jié);無(wú)論如何,了解協(xié)議設(shè)計(jì)的原則,對(duì)深入理解系統(tǒng)通信非常有幫助。
(資料圖)
所謂“協(xié)議”,是雙方共同遵守的規(guī)則,例如:離婚協(xié)議,停戰(zhàn)協(xié)議。協(xié)議有語(yǔ)法、語(yǔ)義、時(shí)序三要素:
語(yǔ)法,即數(shù)據(jù)與控制信息的結(jié)構(gòu)或格式;語(yǔ)義,即需要發(fā)出何種控制信息,完成何種動(dòng)作以及做出何種響應(yīng);時(shí)序,即事件實(shí)現(xiàn)順序的詳細(xì)說(shuō)明;畫(huà)外音:后文主要講語(yǔ)法設(shè)計(jì)。
協(xié)議設(shè)計(jì)通常分為三層:應(yīng)用層協(xié)議、安全層協(xié)議、傳輸層協(xié)議。
下面分別看下這三層的協(xié)議應(yīng)該如何選型。
二、應(yīng)用層協(xié)議設(shè)計(jì)應(yīng)用層協(xié)議選型,常見(jiàn)的有三種:文本協(xié)議、二進(jìn)制協(xié)議、流式XML協(xié)議。
(1) 文本協(xié)議
文本協(xié)議是指“貼近人類書(shū)面語(yǔ)言表達(dá)”的通訊傳輸協(xié)議,典型的協(xié)議是HTTP協(xié)議,一個(gè)HTTP協(xié)議的請(qǐng)求報(bào)文樣例如下:
GET / HTTP/1.1User-Agent: curlHost: musicml.netAccept: */*
文本協(xié)議的特點(diǎn)是:
可讀性好,便于調(diào)試;擴(kuò)展性較好,能通過(guò)key:value擴(kuò)展;解析效率不高,一行一行讀入,按照冒號(hào)分割,解析key和value;對(duì)二進(jìn)制不友好,比如語(yǔ)音/視頻等;(2) 二進(jìn)制協(xié)議
二進(jìn)制協(xié)議即binary協(xié)議,典型是IP協(xié)議,以下是IP協(xié)議的一個(gè)圖示:
二進(jìn)制協(xié)議一般包含:一般包含:
定長(zhǎng)包頭;可擴(kuò)展變長(zhǎng)包體;一般每個(gè)字段有固定的含義,以IP協(xié)議為例,前4個(gè)bit表示協(xié)議版本號(hào)(Version);二進(jìn)制協(xié)議的特點(diǎn)是:
可讀性差,難于調(diào)試;畫(huà)外音:打日志一般需要一個(gè)toString()函數(shù)增強(qiáng)可讀性。擴(kuò)展性不好,如果要擴(kuò)展字段,舊版協(xié)議就不兼容了,所以設(shè)計(jì)時(shí)一般會(huì)有一個(gè)Version字段;解析效率超高,幾乎沒(méi)有解析代價(jià),二進(jìn)制流的每個(gè)字段表示固定含義;天然支持二進(jìn)制流 ,比如語(yǔ)音/視頻;這是一個(gè)典型的16字節(jié)二進(jìn)制定長(zhǎng)包頭的例子:
//sizeof(cs_header)=16struct cs_header { uint32_t version; uint32_t magic_num; uint32_t cmd; uint32_t len; uint8_t data[];}__attribute__((packed));
其中:
(1)前4個(gè)字節(jié)表示版本號(hào)version;
(2)接下來(lái)4個(gè)字節(jié)表示魔法數(shù)字magic_num,用來(lái)解決數(shù)據(jù)錯(cuò)位或丟包問(wèn)題;
畫(huà)外音:例如,約定好魔法數(shù)字是0x01020304,收到的報(bào)文,魔法數(shù)字匹配,認(rèn)為是正常報(bào)文,否則認(rèn)為是報(bào)文異常,斷開(kāi)連接。
(3)接下來(lái)4個(gè)字節(jié)表示命令號(hào)command,不同的命令號(hào)對(duì)應(yīng)不同的變長(zhǎng)包體;
(4)最后4個(gè)字節(jié)表示包體長(zhǎng)度length,以確定變長(zhǎng)包體有多少字節(jié);
這是一個(gè)實(shí)際的二進(jìn)制變長(zhǎng)包體:
message CUserLoginReq { optional string username = 1; optional string passwd = 2;}message CUserLoginResp { optional uint64 uid =1;}
它使用的是Google的Protobuf協(xié)議,容易看到:
請(qǐng)求報(bào)文傳入的是用戶名與密碼;響應(yīng)包返回的是用戶的uid;PB是很流行的二進(jìn)制變長(zhǎng)包體協(xié)議,其優(yōu)點(diǎn)為:
通用,可以生成C++、Java、PHP等多語(yǔ)言代碼;自帶壓縮功能;對(duì)二進(jìn)制友好;在工業(yè)界已廣泛應(yīng)用;畫(huà)外音:Google出品,必屬精品。流式XML協(xié)議流式XML似乎是文本協(xié)議的一個(gè)特例,亦可以單獨(dú)作為一類。例如:xmpp就是典型的流式XML協(xié)議,下面是xmpp協(xié)議的一個(gè)典型報(bào)文:
從xml標(biāo)簽中大致可以判斷這是一個(gè)romeo發(fā)給juliet的聊天消息。 XML協(xié)議有幾個(gè)特點(diǎn): 安全層協(xié)議設(shè)計(jì),除了使用SSL,自行實(shí)現(xiàn)的話,常見(jiàn)的又有以下三種方案。 畫(huà)外音:SSL秘鑰管理是個(gè)問(wèn)題。 (1) 固定密鑰 服務(wù)端和客戶端約定好一個(gè)密鑰,同時(shí)約定好一個(gè)加密算法(例如:AES),每次客戶端發(fā)送報(bào)文前,就用約定好的算法,以及約定好的密鑰加密再傳輸,服務(wù)端收到報(bào)文后,用約定好的算法,約定好的密鑰再解密。 畫(huà)外音:安全性低,安全性基于程序員的職業(yè)操守。 (2) 一人一密 簡(jiǎn)單來(lái)說(shuō),就是一個(gè)人的密鑰是固定的,但是每個(gè)人之間又不同。常見(jiàn)的實(shí)現(xiàn)方式是: (3) 一次一密 即動(dòng)態(tài)密鑰,一Session一密鑰的安全性更高,每次會(huì)話前協(xié)商密鑰。密鑰協(xié)商的過(guò)程要經(jīng)過(guò)2次非對(duì)稱密鑰的隨機(jī)生成,1次對(duì)稱加密密鑰的隨機(jī)生成,具體詳情這里不展開(kāi)。 可選的協(xié)議有TCP和UDP,現(xiàn)在基本都是使用TCP,有了epoll等技術(shù)后,多連接就不是瓶頸了,單機(jī)幾十萬(wàn)鏈接沒(méi)什么問(wèn)題。 標(biāo)簽:
- 環(huán)球熱訊:5G對(duì)企業(yè)業(yè)務(wù)意味著什么?
- 天天視訊!電信業(yè)發(fā)起CNF革命:VM退,容器進(jìn)
- 小米平板新品獲得了3C認(rèn)證 支持67W有線快充
- 世界看熱訊:為什么WiFi 7要看6GHz頻段的“臉色”?
- 環(huán)球時(shí)訊:蓄電池要“下電”,不要太卷!
- 全球熱文:誰(shuí)家的加密密鑰,寫(xiě)死在代碼里?
- 全球新消息丨聊聊實(shí)現(xiàn) 6G 愿景所需技術(shù)進(jìn)步的問(wèn)題
- 環(huán)球熱點(diǎn)!當(dāng)“無(wú)線網(wǎng)”邂逅“零漫游”:銳捷植根行業(yè)場(chǎng)景出新招 原創(chuàng)
- 焦點(diǎn)速遞!聊聊WiFi的前世與今生
- 性能小鋼炮 聯(lián)想小新Pro14多道復(fù)雜工藝打造簡(jiǎn)約金屬機(jī)身