基於傳輸層TCP、UDP協議的自定義應用層協議如何實現?
我知道傳輸層協議的工作原理,對於應用層只了解HTTP協議。根據我的理解,HTTP的工作方式是通過TCP鏈接傳輸具有特定結構的純文本HTTP報文,通過伺服器解析報文來理解瀏覽器的請求實現瀏覽器和伺服器通信。
那麼,其他的應用層協議,都是通過TCP或UDP發送這種約定好結構的純文本數據,在通信的兩端對純文本進行解析來進行通信的嗎?如果想自定義應用層協議,只需要這麼做就可以嗎?還有其他方式嗎?
——————————————————
通過@invalid s的回答,我弄清了我的問題是什麼:
是不是所有的應用層協議都是文本協議?
但是顯然還有一種叫做「二進位協議」,我剛剛知道。
所以我現在的疑惑是,常見的應用層協議中哪些是文本協議,哪些是二進位協議?另外我們自定義應用層協議的時候,一般採用哪種比較合適?
10.17 更新補充
………………………………
有一些協議可能不是直接全部分析二進位或者先全部轉碼後分析,而是可能兩者都有。比如websocket,則是直接先解析二進位數據,拿到報文中哪幾個位元組是數據部分的信息,然後截取這段數據進行轉碼,這段數據進行轉碼後作為數據內容部分。
……………………………………
遠答案:
應用層直接拿到的都是二進位的,文本協議也是解析二進位拿到文本,然後分析文本。二進位協議應該是直接分析二進位數據,不需要再次進行 toString 這類方法先拿到一個中間數據格式(http就是先轉普通文本),然後再次進行解析。其他應用層, redis 通信使用的是文本協議。
文本是給人看的,不需要人參與的應用不需要定義成文本的。比如遠程控制車輛,遠程控制機器人。
http設計成文本是因為他本來就是給文本設計的。大部分應用層協議都不是文本的,比如ftp,rtp之類的。
所有協議都有信令和業務兩部分。一般情況下設計,業務部分隨應用內容走。例如傳圖片不可能用文本。信令部分一般是二進位的,優點是效率高。缺點是擴展性差。
以前的二進位協議是設計死的欄位和比特。現在新的設計方向是tlv格式(type-length-value),擴展性強。效率依然很高。
文本的協議設計方向是用xml格式,擴展性也好。文本協議便於和資料庫的聯動,尤其是xml格式更好。二進位協議想對接各種資料庫需要轉換。http恰好需要資料庫訪問和對接。
從安全性上來說,tlv和xml都有惡意格式和長度溢出等攻擊,如果用固定格式的二進位會好一些。改成這樣就對了:
所有的應用層協議,都是通過TCP或UDP發送某種符合約定的二進位數據,然後在通信的兩端對二進位數據進行解析來進行通信的。
————————————————————————————————
文本協議只適合簡單的、小規模的使用。
稍微複雜一點,靠人眼去找格式錯漏之處,純屬扯淡;尤其是條目眾多、狀態複雜時,基本是不可能的。
可一旦上自動化工具……還是格式固定的二進位協議編程處理起來更為省心省力;處理之後人再看就沒什麼區別了。
http本來就是「超文本傳輸」協議,所以才會用文本格式的協議。
除了很少一些例外,大規模使用的協議很少會是基於文本的。
你經常接觸到的,包括各種聊天工具、各種網路遊戲、文件下載/分享的FTP/BT等等等等,都是二進位的——所以題主其實應該問「究竟有哪幾個經常用到的協議是文本協議」才對。
文本協議的好處是如下兩點:
1,格式模糊,編程處理雖然略為麻煩,但當需求不甚明確時,這類「格式化文本」比較抗改,不太容易改的無法識別;而且當發送/接受端程序設計出現bug、不能很好處理它時,也不太容易引起故障。
2、人眼可讀,小作坊生產時,無需開發配套工具。
所以,它比較適合不成熟的原型系統、無需考慮執行效率的企業開發等場合使用。
但現在有google的protocol buffer,你給它格式化文本,它就自動給你轉換成二進位協議,工具鏈齊全;除非玩具性質的項目,是時候和不專業且臃腫昂貴的文本協議說拜拜了。
https://developers.google.com/protocol-buffers/基於二進位的協議機器解析起來比較快,但人工閱讀困難,基於文本的則相反。由於機器的處理能力可以快速增長,而人的閱讀能力難以增長,所以基於文本的協議越來越流行。
協議是否複雜,取決於要實現的目標是否複雜,前邊很多人提到了,簡單的如同echo,複雜的如同http。
推薦一本書
《網路協議工程》(吳禮發)【摘要 書評 試讀】
網路協議是計算機網路及數據通信的核心,開發正確、有效的網路協議一直是人們追求的目標。協議工程是指集成化、形式化的協議開發過程,其目的是減少協議開發中潛在的錯誤,提高協議開發的效率和質量。《網路協議工程》以協議工程活動所涉及的各種技術為主線,以介紹基本原理、技術與方法為原則,主要內容包括:協議工程概論、協議設計技術、協議形式化描述技術、協議形式描述語言、協議驗證技術、協議驗證工具、協議一致性測試技術等。各章均附有討論題、思考題及參考文獻。
目錄
第1章 概述
1.1 協議
1.1.1 定義
1.1.2 協議的標準化
1.2 協議工程
第2章 協議設計技術
2.1 協議模型
2.2 協議設計的基本內容
2.2.1 協議的通信環境
2.2.2 協議提供的服務
2.2.3 協議功能
2.2.4 協議元素
2.2.5 協議組織
2.2.6 協議文本
2.3 協議設計方法
2.3.1 協議設計原則
2.3.2 分層次的協議設計
2.3.3 自頂向下的協議設計
2.4 差錯控制技術
2.4.1 差錯類型
2.4.2 差錯檢測技術
2.4.3 差錯控制技術
2.4.4 差錯控制與層次的關係
2.5 流量控制技術
2.5.1 X-on/X-off協議
2.5.2 滑動窗口協議
第3章 協議形式化描述技術
3.1 概述
3.2 FSM
3.2.1 FSM的基本概念
3.2.2 FSM的簡化
3.2.3 FSM的錯誤模型
3.2.4 FSM的合併
3.2.5 擴展的有限狀態機(EFSM)
3.3 PetriNet
3.3.1 Petri網的基本概念
3.3.2 Petri網的擴充
3.3.3 Petri網的性質
3.3.4 Petri網在協議描述中的應用
3.4 時序邏輯
3.4.1 基本概念
3.4.2 時序邏輯系統
3.4.3 時序邏輯在協議描述中的應用
3.5 通信順序進程
3.5.1 概述
3.5.2 CSP在協議描述中的應用
第4章 協議形式描述語言
第5章 協議驗證技術
第6章 協議驗證工具
第7章 協議一致性測試技術
附錄A 英文縮略詞
直接回答什麼情況用 human-readable 的文本協議,什麼情況用二進位協議。
文本協議:- 對協議頭的 size 沒特別要求
- 對解析速度沒特別要求
- 需要協議輕鬆支持變長 header 且保持較友好的擴展性(如像 HTTP 一樣可以隨意增加 header)
- 升級協議且不增加協議本身複雜度
- 對於協議的調試友好程度要求高
哈哈~ 其實對於這樣的要求,通常直接使用 HTTP 就可以了,不需要自己設計協議。:-)
二進位協議:- 要求協議頭 size 要足夠小
- 要求解析速度要足夠快
- 協議頭相對較固定,變動的可能性較低,但仍然需要留一些擴展位
舉一個栗子,比如即時通訊就很適合用二進位協議,因為即時通訊需要頻繁收發消息,對於傳輸和解析的速度都有比較高的要求。
這基於你的業務需求。。。人月神話里說過,沒有銀彈
文本協議和二進位協議的區別,主要的是以下幾點
1,解析的效率
2,消息包的大小
3,協議的擴展性
先說解析效率,二進位的解析效率高,因為哪個位置是什麼內容已經很明確了,文本協議,例如常見的json,xml,其解析起來慢得多了
再說消息包的大小,明顯是二進位的包更小。比如保存一個時間戳,二進位用4位元組整數足夠了,文本協議就要一個至少10位元組的字元串
擴展性那必須是文本協議更強。
協議並沒有那麼複雜,最簡單的如echo服務,客戶端說一句話,伺服器原話回復也就是一種協議了。至於文本協議、二進位協議,其實更大意義上是對於人類而言的。
文本協議的解析單位是位元組,主要是考慮可讀性和通用性,受過一定訓練的人不依賴特定客戶端直接使用,如IMAP, POP, SMTP, HTTP等。
二進位解析單位是位,可想而知信息密度要比文本大,就是說一般情況下採用二進位協議傳輸效率上會更高,但是對於一般人類,即使知道包的格式也很難徒手使用。
如何實現,使用哪種方式完全取決於你的應用場景。是約定的封裝結構,實際業務數據會逐級封裝報頭,客戶端收到比特流後進行解封裝,http是封裝在tcp內的
Http,ftp這種應用層協議是種標準,目前所有的web容器和客戶端均差不多嚴格的按此標準實現。你當然可以實現自己的協議,只要你開發自己的web容器和客戶端即可
HTTP默認使用TCP的80埠標識
FTP默認使用TCP的21埠標識
SMTP默認使用TCP的25埠標識
POP3默認使用TCP的110埠
HTTPS默認使用TCP的443埠
DNS使用UDP的53埠
遠程桌面協議(RDP)默認使用TCP的3389埠
Telnet使用TCP的23埠
Windows訪問共享資源使用TCP的445埠
雖然你終將平凡,但是請勿忘初心 " 手把手教你實現自定義的應用層協議 這裡有詳細講解和代碼實現。
個人理解:
底層協議使用二進位協議,照顧性能。
傳輸層協議需要覆蓋的場景廣泛,層四之上的協議都是基礎傳輸層協議的再次實現,如果傳輸層協議使用文本,會導致有效載荷比例太低,網路中冗餘信息量暴增。嚴重影響性能。
上層協議使用文本協議,好定位問題,也不一定會再次封裝,不用太刻意在意性能。
把HTTP協議看成一個基於TCP協議的自定義協議就好,你自己已經領悟到了:
http協議有header,body。
header和body有協議好的間隔。
header里包含此次傳輸數據的元數據信息,包括編碼和body長度,也就是告訴你如何爭取取出body數據。
同時http協議本身規定好了一些參數:encode,method、etag之類的,那你的自定義協議也可以規定,如果是基於二進位的,就好比已經規定好:
第一個參數幾個位元組,第二個參數幾個位元組,第三個參數是變長,變長參數的位元組長度;
具體可以參看SIP協議,基於TCP的二進位協議。
推薦閱讀:
※前端工程師應該對 HTTP 了解到什麼程度?從哪些途徑去熟悉更好?
※為什麼國內視頻網站多採用HTTP協議傳輸視頻,而國外多使用RTMP等專門的流媒體協議?