二進制協議 VS 文本協議
前言
最近由於工作上的需要(一方面是與底層與傳感器進行數據交互,另一方面是對RabbitMQ的AMQP協議的學習),接觸了一些網絡協議相關的內容。正好就二進制協議與文本協議的一些問題簡單說一些。
二進制協議(binary protocol)
概念
協議:就是一組大家約定俗成的契約,大家都遵守。而計算機領域的協議,大多指的就是網絡協議。
網絡協議:計算機網絡中進行數據交換而建立的規則、標准或約定的集合。說直白點,就是大家約定XXX網絡協議下的數據怎么接收,怎么處理,怎么發送等。
二進制協議(Binary protocol):
Wiki: A binary protocol is a protocol which is intended to be read by a machine rather than a human being, as opposed to a plain text protocol such as IRC, SMTP, or HTTP/1.1. Binary protocols have the advantage of terseness, which translates into speed of transmission and interpretation.
Binary protocol is also used in the context of a protocol between exactly two parties, in contrast to a multi-party protocol. Binary protocol, or binary collaboration have been used in the terminology of standards such as EbXML, HTTP/2 and EDOC.[1] An interface in UML [2] may also be considered a binary protocol.
簡單來說,就是二進制協議在進行網絡傳輸時,傳輸的並不是類似JSON這樣的文本文件,而是類似BSON這樣的二進制數據。
(Java中字節流采用的是ASCII碼,而字符流采用的是Unicode碼)
優點
- 空間占用小(包括內存,帶寬等)
- 運算規則簡單(如加密就方便)(畢竟來來回回就0和1)
- 可靠性高(不是0就是1,還有校驗和等技術實現驗證。文本協議與之對應的就是數字簽名)
- 部分技術場景實現方便(典型的底層硬件,如傳感器。因為底層本就是0和1構成的數據,不需要轉換)
缺點
- 可讀性差(由此延伸出記憶困難等問題,畢竟位數太多了,還全是0和1,就是機器碼啊。所以協議的每條命令都要有對應的文檔進行細致說明,包括二進制文件采用的是哪種編碼方式等)
- 擴展性差(並不是不可以進行消息的擴展,而是已經確定的數據解析順序,是不可以改變的)
- 無法跨處理器(據說是由於嚴格的內存到對象的轉換。個人的理解是,由於不同處理器架構存在數據存儲的大端小端問題而導致的。)
- 部分技術場景實現復雜(例如,原先只要通過JSON,就能獲取所需數據。而現在,你首先要獲取二進制流,可能還需要進行拆包與粘包工作,從而獲得二進制數據。再根據協議,一條條地解析命令字與數據域。不要問我為什么這么清楚,說多了,都是淚。之后有機會,會講解一下的)
舉個栗子
TCP:一種面向連接的、可靠的、基於字節流的傳輸層通信協議,由IETF的RFC 793定義。
首先,我們從網絡模型的角度來考慮。TCP位於傳輸層,接收上一層的數據,對數據進行必要的分割,並將數據交給網絡層,且保證這些數據的准確到達(三次握手)。所以,作為傳輸層的協議,TCP主要任務是傳輸與數據分割。那么很明顯,采用二進制數據進行傳輸時最好的選擇。傳輸層能夠充分發揮二進制協議空間占用小(帶寬消耗低),可靠性高(提高數據傳輸的可靠性),運算規則簡單(便於數據的分割等工作)等優點。並由於傳輸層特性,降低了其缺點所帶來的影響。說到這里,不得不說層次架構是個好東西,其典型代表的網絡模型,更是如此。其次,了解TCP報文結構的朋友想象一下。如果TCP不是二進制協議,而是一個文本協議,那么其中的TCP Flags,Checksum等的實現會不會變得冗余,繁瑣。所以,TCP是一個二進制協議。與此同時,TCP協議也是二進制協議的一個典型代表。
其他:UPD,IP,PPP,Protobuf,MQTT,AMQP等典型例子類比分析即可,不再贅述。
使用場景
相對於文本協議而言,二進制協議的自定義更具區分度,數量也更多。原因也很簡單,正如之前所說,二進制協議相對文本協議擴展性更差,可讀性更差,這也就造成其復用性很差。往往不同產品,項目間的二進制協議差別也許不大(本來就是比較底層的東西,沒有太高的復雜性),但就是不能共用(也許就是協議中,數據的標示符,命令字等區域位置,長度有所不同)。所以,二進制協議的自定義較為常見。
以自身為例,我負責的物聯網項目中的終端程序需要與不同傳感器進行交互。而大多第三方的硬件廠商並不會采用諸如MQTT這樣的網絡協議,他們往往會自定義一個二進制協議,來與上層通信(畢竟硬件實現MQTT這樣的標准化協議,也是需要成本投入的)。例如我解決交互的第一個傳感器526,其實通過串口通信(這個,有點古老)。它的數據幀是這樣的:
很明顯,這樣的規定很是“死板”,Java中,通過RXTX監聽對應串口,並接收數據數組(這里可能涉及到數據的粘包,拆包工作。當然,如果數據接收頻次不高,並且不是連續數據,可以通過sleep或wait等來暫停一下,確保數據接收完畢)。之后,根據第三方廠商所給數據幀格式,對命令,數據域進行解析(這里就必須很死板地根據對應位置讀取對應數據,另外數據域可能采用BCD碼)。最后根據命令字,對數據進行相關操作。
這個時候,我們再看一下,同一廠商下同一產品線,型號略有不同的產品826,它的數據幀與前面的526其實差不過。
但是,兩者的區別在於,前者數據域的每個數據都是三個字節的,而后者則是四個字節的。所以得重寫。當然,如果接入的第三方自定義協議越多,就越好做抽象,從而達到一定的復用(當然,效果肯定是不能和文本協議相比較的)。
文本協議(Text-based protocol)
概念:
文本協議(Text-based protocol):
Wiki:A text-based protocol or plain text protocol is a communications protocol whose content representation is in human-readable format.
The immediate human readability stands in contrast to binary protocols which have inherent benefits for use in a computer environment (such as ease of mechanical parsing and improved bandwidth utilization).
簡單來說,就是文本協議在進行網絡傳輸時,傳輸的是類似JSON,XML這樣的文本文件,而不是二進制文件(就是0和1)
概念擴展:
一般來說,這個時候,就該有人要抬杠了。一般可以分為兩種,這里我們就HTTP這一文本協議為例子討論。第一種,有人提出HTTP協議的底層依舊是0和1,它怎么就是文本協議了。答案就是一個協議是不是文本協議,與它在網絡模型的上下層協議無關,只與自身相關。第二種,有人提出HTTP可以用來傳輸圖片(寫過類似NODE.JS服務器原始請求,就是返回值類型,需要專門指定。會明白圖片傳輸是采用二進制的),那么HTTP還能算文本協議嘛。答案就是它是不是文本協議,取決於它是否能夠利用文本的格式來進行通信,很明顯它可以,所以它是文本協議。這也避免有人拿telnet能進行二進制通信來抬杠。當然,國外也有人提出是不是文本協議不取決於它能否對二進制數據進行編碼(UTF,ASCII),而是取決於協議是圍繞數據結構,還是文本字符串。最后,上述HTTP協議是指HTTP1.1,而HTTP2是二進制協議(根據這點,國外那位的觀點,需要稍作修改:在傳輸的數據是否具備數據結構)。
優點&缺點
二進制協議的優缺點轉換一下就OK了,不在贅述。
舉個栗子
HTTP1.1:基於請求-響應模型,無狀態,無連接的應用層協議。
其他:FTP,TELNET等。
使用場景
乍一看,貌似平時大家開發的協議貌似大多是二進制協議,什么RPC,AMQP,就連Kafka都是基於TCP自寫的二進制協議。不過之前就說了,二進制協議缺乏復用性,所以多是肯定的嘛。但是用得最多的還是HTTP這樣的文本協議。平時前后端進行的交互,就是基於HTTP的,也就是文本協議的。一般來說,我們直接用的都是文本協議,即使涉及二進制協議,也是對二進制協議進行了一定封裝(如kafka的java API,AMQP的API)后的調用。
總結
多數情況下,很多人可以寫了好幾年都碰不到幾回二進制協議,但是一旦進了二進制協議的坑(一方面是物聯網中與硬件交互,另一方面是研究什么MQ的通信協議啊),然后就只能說一句,真香。
好吧,開個玩笑。其實兩種協議各有利弊,沒有銀彈,只有適用場景。說幾個主要的考慮點,首先從成本(包含學習成本,時間成本等)來看,文本協議肯定是優於二進制協議的,否則,也不會那么多人不了解二進制協議了。其次從效率(包括帶寬等資源消耗,數據處理等)來看,二進制協議肯定是優於文本協議的,否則,也不會那么多MQ采用二進制協議了。然后從可讀性來看,文本協議肯定是由於二進制協議的,當然這也帶來了學習成本(包括熟悉二進制協議,如數據幀等)。最后從擴展性與安全性來看,二進制協議雖然有一定擴展性,導致開發的時間成本上升。但我認為如果數量較多,形成協議族效果,其實成本也就沒那么高了(畢竟二進制協議中很多工具是通用的,數量優勢也可以完成良好的抽象)。安全性方面,二進制協議有天生的優勢(全是0和1),其編碼規則只有收發雙方了解,加解密也方便。