首頁>技術>

系統設計,協議先行。

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

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

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

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

一、協議的分層設計

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

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

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

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

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

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

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

二、應用層協議設計

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

文字協議

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

GET / HTTP/1.1User-Agent: curlHost: musicml.netAccept: */*

文字協議的特點是:

(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)=16struct 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協議的一個典型報文:

<messageto=’romeo@example.net’from=’juliet@example.com’type=’chat’xml : lang=’en’><body>Wherefore art thou, Romeo?</body></message>

從xml標籤中大致可以判斷這是一個romeo發給juliet的聊天訊息。

XML協議有幾個特點:

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

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

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

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

三、安全層協議設計

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

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

固定金鑰

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

畫外音:安全性低,安全性基於程式設計師的職業操守。

一人一密

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

(1)固定加密演算法;

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

一次一密

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

四、傳輸層協議設計

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

  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • C語言這麼厲害,它自身又是用什麼語言寫的?