天天看點

一次徹底搞透協定設計(沒做過通訊底層也沒有關系)!

系統設計,協定先行。

大部分人不了解協定的設計細節,更多使用已有協定進行應用層設計,例如:

(1)使用HTTP,設計get/post/cookie參數,以及json包格式;

(2)使用dubbo,而不用去深究内部的二進制標頭包體細節;

無論如何,了解協定設計的原則,對深入了解系統通信非常有幫助。

一、協定的分層設計

所謂“協定”,是雙方共同遵守的規則,例如:離婚協定,停戰協定。協定有文法、語義、時序三要素:

(1)文法,即資料與控制資訊的結構或格式;

(2)語義,即需要發出何種控制資訊,完成何種動作以及做出何種響應;

(3)時序,即事件實作順序的詳細說明;

畫外音:後文主要講文法設計。

協定設計通常分為三層:應用層協定、安全層協定、傳輸層協定。

一次徹底搞透協定設計(沒做過通訊底層也沒有關系)!

下面分别看下這三層的協定應該如何選型。

二、應用層協定設計

應用層協定選型,常見的有三種:文本協定、二進制協定、流式XML協定。

一次徹底搞透協定設計(沒做過通訊底層也沒有關系)!

文本協定

文本協定是指“貼近人類書面語言表達”的通訊傳輸協定,典型的協定是HTTP協定,一個HTTP協定的請求封包樣例如下:

GET / HTTP/1.1
User-Agent: curl
Host: musicml.net
Accept: */*           

文本協定的特點是:

(1)可讀性好,便于調試;

(2)擴充性較好,能通過key:value擴充;

(3)解析效率不高,一行一行讀入,按照冒号分割,解析key和value;

(4)對二進制不友好 ,比如語音/視訊等;

二進制協定

二進制協定即binary協定,典型是IP協定,以下是IP協定的一個圖示:

一次徹底搞透協定設計(沒做過通訊底層也沒有關系)!

二進制協定一般包含:

(1)定長標頭;

(2)可擴充變長包體;

(3)一般每個字段有固定的含義,以IP協定為例,前4個bit表示協定版本号(Version);

二進制協定的特點是:

(1)可讀性差,難于調試;

畫外音:打日志一般需要一個toString()函數增強可讀性。

(2)擴充性不好,如果要擴充字段,舊版協定就不相容了,是以設計時一般會有一個Version字段;

(3)解析效率超高,幾乎沒有解析代價,二進制流的每個字段表示固定含義;

(4)天然支援二進制流 ,比如語音/視訊;

這是一個典型的16位元組二進制定長標頭的例子:

//sizeof(cs_header)=16
struct cs_header {
  uint32_t version;
  uint32_t magic_num;
  uint32_t cmd;
  uint32_t len;
  uint8_t data[];
}__attribute__((packed));           

其中:

(1)前4個位元組表示版本号version;

(2)接下來4個位元組表示魔法數字magic_num,用來解決資料錯位或丢包問題;

畫外音:例如,約定好魔法數字是0x01020304,收到的封包,魔法數字比對,認為是正常封包,否則認為是封包異常,斷開連接配接。

(3)接下來4個位元組表示指令号command,不同的指令号對應不同的變長包體;

(4)最後4個位元組表示包體長度length,以确定變長包體有多少位元組;

這是一個實際的二進制變長包體:

message CUserLoginReq {
  optional string username = 1;
  optional string passwd = 2;
}



message CUserLoginResp {
  optional uint64 uid =1;
}           

它使用的是Google的Protobuf協定,容易看到:

(1)請求封包傳入的是使用者名與密碼;

(2)響應包傳回的是使用者的uid;

PB是很流行的二進制變長包體協定,其優點為:

(1)通用,可以生成C++、Java、PHP等多語言代碼;

(2)自帶壓縮功能;

(3)對二進制友好;

(4)在工業界已廣泛應用;

畫外音:Google出品,必屬精品。

流式XML協定

流式XML似乎是文本協定的一個特例,亦可以單獨作為一類。例如:xmpp就是典型的流式XML協定,下面是xmpp協定的一個典型封包:

<message

to=’[email protected]’

from=’[email protected]’

type=’chat’

xml : lang=’en’>

<body>Wherefore art thou, Romeo?</body>

</message>           

從xml标簽中大緻可以判斷這是一個romeo發給juliet的聊天消息。

XML協定有幾個特點:

(1)可讀性好,擴充性好,這是XML的特性;

(2)解析代價超高,需要進行dom樹分析;

(3)有效資料傳輸率超低,有大量的标簽;

三、安全層協定設計

安全層協定設計,除了使用SSL,自行實作的話,常見的又有以下三種方案。

畫外音:SSL秘鑰管理是個問題。

固定密鑰

服務端和用戶端約定好一個密鑰,同時約定好一個加密算法(例如:AES),每次用戶端發送封包前,就用約定好的算法,以及約定好的密鑰加密再傳輸,服務端收到封包後,用約定好的算法,約定好的密鑰再解密。

畫外音:安全性低,安全性基于程式員的職業操守。

一人一密

簡單來說,就是一個人的密鑰是固定的,但是每個人之間又不同。常見的實作方式是:

(1)固定加密算法;

(2)加密秘鑰使用“使用者的某一特殊屬性”,比如使用者uid、手機号、qq号、使用者密碼等;

一次一密

即動态密鑰,一Session一密鑰的安全性更高,每次會話前協商密鑰。密鑰協商的過程要經過2次非對稱密鑰的随機生成,1次對稱加密密鑰的随機生成,具體詳情這裡不展開。

四、傳輸層協定設計

可選的協定有TCP和UDP,現在基本都是使用TCP,有了epoll等技術後,多連接配接就不是瓶頸了,單機幾十萬連結沒什麼問題。

一次徹底搞透協定設計(沒做過通訊底層也沒有關系)!

架構師之路-分享可落地的技術文章

繼續閱讀