二進位制協議 VS 文字協議

血夜之末發表於2019-05-08

二進位制協議 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,其實通過串列埠通訊(這個,有點古老)。它的資料幀是這樣的:

二進位制協議 VS 文字協議

很明顯,這樣的規定很是“死板”,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),其編碼規則只有收發雙方瞭解,加解密也方便。