如何自定義一個通信協議


借鑒簡單的OSI和TCP/IP通信模型來討論如何自定義一個適應自己的通信協議

 

 


1.前言

在物聯網的通信中,很多地方需要自定義協議。但考慮到平時工作中接觸到的自定義協議,都或多或少存在一些問題和缺陷。所以想借鑒之前看過的書上的知識以及一些國際標准的協議,來簡單談談如何設計一個自定義通信協議,並且通信方都遵守這個協議,並如何談談根據自己的需求對協議進行簡化。
除此之外,考慮到后面可能不太會接觸這一塊,所以可能是一次集中性的大清理,后面可能會整理一下底層(單片機)上一般如何處理數據接受發送的問題,大概會以lwip為例。
收集的資料會有些不全,如果有什么比較特別的協議可以在評論指出。下面也是按我自己對這個協議理解的角度來講。為了節省篇幅着重點,中間會省去一些基本的概念。

這里會省去一些通信的基本概念,着重分析協議,分析每層的目的和協議組成,不分析原理。

這里補充一點,也是突然上次有人和我說我才想起來,除了我們用相互規定的數據流來表示內容外,還有一種協議的表示方法:可以用字符串解析,這種可以參考HTTP沒什么太多需要解釋的。只不過字符串的內容和方式通信方自定義。不過個人認為這種方式對嵌入式來說沒太多必要,太浪費有限的帶寬,同時解析速度也很慢。不過就算是HTTP的下面層也是TCP,IP數據鏈路之類的,依然是要通過數據流的層次上進行包裝,只是對應用層的解析上比較直觀罷了。

2.經典的OSI七層模型

這里首先以經典的OSI七層模型介紹整個通信從物理層到應用層的的層次分層。分層有助於分離出不同層的處理任務和職責,不同層之間通過接口由下一層向上一層提供服務。此外,分層設計的也會過分的模塊化,使處理變得繁重。
下面是模型的圖示:

這里寫圖片描述

(盜了一張圖,各層次的簡單功能都寫在旁邊了。附上出處地址:http://blog.sina.com.cn/s/blog_4770ef020101i1wd.html

這個模型分的很細,中間增加了很多保證速度,數據可靠性,安全等的機制。在我們應用的時候,根據需求不同,有着不同的側重點。有的時候需要的只是一些簡單的數據傳輸功能,有的時候我們借助了硬件模塊(模塊自身已經實現了協議),或者需要實現協議棧,每種還需要根據結合情況,制定的協議有所不同。

從很多通信模型中都不難看出,其實基本都逃不出這個模型,他們很多都是根據自己的需要在模型的基礎上做些刪減和簡化。

2.1.TCP/IP模型解析

2.1.1.整體介紹

TCP/IP是將OSI模型進行部分的簡化,將7層模型壓縮為4層模型。不過兩者的側重點不太一樣。OSI是列出了通信的基本協議,以及具體如何分層,划分職責。TCP/IP則側重具體協議的實現。

對應分層如下圖所示。圖片出處:http://www.lxway.com/925941824.htm

TCP/IP協議整體的感覺大概就是下面這個樣子。每一層會在數據的前面加一個首部,中間包含了那一層對應的控制信息。(這里補充一下:數據可以用包,幀,數據包,段,消息來描述。)

這里寫圖片描述

這里寫圖片描述

2.2.2.數據鏈路層

首先是把物理層和數據鏈路層合並,定義了通信媒介互聯設備間的傳輸規范。這一層往往對應的是設備驅動程序和網絡接口。物理層實現數據0,1轉化,數據鏈路層把數據集合成幀,同時需要保證電子線路上的可靠性。這層還是比較注重數據的傳輸方式,網絡的拓撲結構等物理方面的處理。
除去線路上的物理連接外,還使用了MAC地址來識別不同的連接對象。因此這層的數據首部中會加入MAC地址信息。通常MAC地址是有設備制造商決定的,並且是唯一的(虛擬機的那種??除外)。

以太網是數據鏈路中最著名的一種。這里以以太的數據鏈路層的協議規定示范,其他的不同協議的數據鏈路層規范也都不一樣,如下圖。

這里寫圖片描述

可以看出這層協議的首部主要有MAC地址和控制以太類型。在以太幀格式前面有一段前導碼。由0,1交替組成,用來做前導碼(8字節),以一個SFD的域(11)作為前導碼的結尾。
以太幀的頭部一共有14字節,目的MAC和源MAC,再加2字節的上層協議類型(決定下一層網絡層接受的數據類型)。幀尾的FCS為幀校驗序列,用來排除硬件噪聲的干擾導致的錯誤

2.2.3.網絡層

網絡層單獨對應一層,和OSI的網絡層相同。這層主要負責將數據送到正確的目的地址。這里的地址是IP地址,每個連接入網絡的設備都需要有個IP地址,IP地址由網絡號和主機號組成。這樣看上去就可以按地區分配(這里是有ISP和區域網分配出來的),並且比較固定和集中,而不會像MAC地址一樣無規律分布。這樣加快了數據傳輸雙方尋址的速度(對於很大的大網絡更加明顯)。這里有個關系,IP尋址是靠路由控制表,同時IP和MAC地址由地址轉發表控制。

這層可以不管底層是用那種數據鏈路進行通信的(可以跨越不同的數據鏈路,比如WIFI和網線的混連),只負責路由實現節點間的路由通信,同時也不會涉及重發機制,這部分是傳輸層需要做的工作。

對於下一層的數據鏈路層來說,網絡層同時可以屏蔽不同數據鏈路的傳輸問題,這里使用了IP分片處理方式。IP包會根據不同鏈路進行重組。這應該都是路由器的工作,從而使上層忽略掉數據鏈路層的影響。而對於上層來說,IP提供的是無連接的服務,這樣雖然會有很多冗余,但會提高速度。如果要保證可靠性,可以靠上的傳輸層來保證。

這層的核心是IP協議,它是基於地址轉發分包數據的,跟在數據鏈路層首部的后面,協議格式具體如圖所示:此外還有些輔助性的測試協議比如ICMP,地址解析協議ARP等。
這里寫圖片描述

前面有4bit為版本號,標記着這個是什么數據,比如說是IPV4還是IPV6。接着4bit表示首部長度用來表示首部大小,以4字節為基本單位,默認為5,即20字節。區分服務用一個字節來表示,說明服務質量。總長度表示IP首部與數據部分結合起來的總字數。標識表(2字節),標志(3bit)片偏移,用於分片重組;生存時間表示以秒為單位當前包在網絡中都應該的生存期限。協議表示IP首部的下一個首部隸屬於哪個協議。首部校驗和用來保證首部的正確性。源地址和目的地址為通信雙方的ip地址。

2.2.4.傳輸層

傳輸層也是單獨對應,負責建立連接斷開,保證傳輸的可靠性。這層包括2類很著名的傳輸層協議:TCP和UDP。
這里以TCP為例,TCP是一種面向連接的通信協議,它比UDP復雜。這里TCP主要實現數據傳輸時的控制功能,確認應答,重發機制,連接管理等策略來保證通信的可靠性的。
分析它的格式,具體如下:

這里寫圖片描述

源/目的端口號就是我們平時TCP/IP所說的端口號。序列號是用來確認發送位置的,每發送一次自增1。確認序列號指下一次應該收到數據的序列號,發送端收到這個序列號以后可以認為前面的數據都被正常接收。數據偏移表示首部的長度。控制位有8為,每一位都有特殊的控制標志位。如下圖:

窗口大小是用來表示確認應答號所示位置開始能接受數據的大小。通常不允許超過測出的大小。校驗和來表示數據正確性(注意這里的校驗和,是用於防止數據鏈路層以上的干擾而做的)。緊急指針在應用中處理,一般在暫停中斷通行或者中斷通信情況下使用。選項用於提高TCP的傳輸能力。

這里寫圖片描述

SYN建立連接;FIN斷開連接;RST連接出現異常必須強制斷開;ACK為應答;ECE通知網絡擁塞,CWR通知縮小擁塞窗口。

2.2.5.應用層

應用層包括了原來的應用層,表示層,會話層,中間有很多是為了實現某種特定的應用而制定的協議,所以對於具體的應用有不同的處理。這里以http舉例。
HTTP屬於TCP/IP協議族中的常見的應用服務。HTTP主要應用在Web中。Web中有三個重要的概念:URI,HTML,HTTP。

URI用於識別資源的具體位置。就是我們打開在瀏覽器地址欄輸入的地址。URI可以和HTTP或者HTTPS組合來訪問Web,就像輸入網頁一樣。

HTTP是在接入要訪問的網頁是開始工作的,它的傳輸層協議采用TCP連接,端口號為80,然后再在這個連接上進行請求應答發送數據報文。HTTP提供了一些命令,像常見的有GET,HEAD,POST等。

HTML是WWW通用的數據表現協議,是一種標記語言,類似於OSI的表示層。可以通過標簽的方式將瀏覽器中的內容顯示出阿里,或者設置等。

3.不同類型的通信方式的總結

3.1.從上述模型/協議中獲得的經驗

TCP/IP模型采用分層設計,從OSI模型中演變過來的。但是TCP/IP相對來說比較復雜,畢竟我們上個網用的就是TCP/IP。但是有一說一,講講每個層的特點。
先說數據鏈路層吧。數據鏈路這層是為了規范各種不同的數據鏈路。一個是拓撲結構,一個是物理連接的不同。物理連接不同也會造成數據速度,單次傳輸長度間的差異。從協議的格式上也可以看出這層實現了解決了。
1.硬件地址的表示MAC,解決多機通信的問題。
2.消除了數據鏈路的電磁干擾,保證數據正確性。
3.標記了當前數據鏈路的類型,使上層方便處理。
4.有段前導碼來識別幀的起始。

接着是網絡層,這層主要的任務是數據路由,另外對上層隔離(消除)了數據鏈路層差別的影響。通過IP地址來輔助數據發送或接受。如果沒有那么多的節點,其實這里也不需要,如果節點較少用簡單的地址也能解決。下面是協議中的針對改層的一些重點:
1.標記IP協議相關信息,在這層可以進行不同的處理。
2.對不同的數據鏈路的數據進行分組操作。
3.轉化成IP地址
4.記錄了數據的長度。

傳輸層主要保證連接,確保傳輸的可靠性。但也根據不同的需要,實現有了不同的策略,像分出TCP,UDP等。但這層總體的目的還是控制數據傳輸為主。協議中包括了一些:
1.處理端口號。
2.控制不同的傳輸層協議。
3.連接,斷開,應答,重發等控制。
3.流量控制策略。

應用層其實就是我們最后需要給我們應用量身制定的協議,中間可以按自己的需要給加一些特定的內容,甚至數據加密等。

3.2.幾種的情況的通信協議

3.2.1.簡單的數據傳輸功能

這種方式一般是指數據量較少,而且大多數為一對一,不進行組網的方式。而且選擇的是一些簡單的通信方式,像是USB,串口,485,I2C總線之類的。這個時候協議相當於直接和硬件接觸了。這時候保證數據不受電磁干擾就非常必要了,所以可以在數據的最后加入數據正確性校驗。

3.2.2.借助了硬件模塊/協議棧的通信

這種方式類似於,比如我們用了硬件集成協議棧的模塊,我們只需要對模塊進行配置,剩下就通過借助上一種方式中提到的總線,傳輸數據給模塊或者從模塊讀取數據,模塊會自動幫你發送和接收。但因為和模塊的通信還是有硬件連接的過程,所以還是需要保證硬件的干擾,但節點和節點間的一些問題有的模塊已經忙你處理了。

3.2.3.直接使用socket通信

直接使用socket通信其實和上面的差不多,只不過不需要通過硬件模塊連接這部分,所以協議的內容上也可以功能加自由。但是如果其他端有涉及到硬件的,一些硬件保護措施還是必不可少,除非在集中通信的地方做次協議轉換。

3.3.其他補充

上述只是說要注意寫什么,並不是絕對的,大多數時候還是要根據自己的應用需求來定協議,如果處理速度,數據量跟得上,可以加入足夠的預留,保證除真實數據意外的部分不變,這樣方便后續拓展協議的兼容。預留部分可以層次分開來,但不處理,以后需要拓展的時候再加進來,而不影響整體。但是如果是一次性的開發,或者保證不會出現那么多的,可以適當裁剪來減少負擔。

另外TCP/IP中經常出現一些協議的版本的分辨標記,如果不是專門去做協議棧,個人認為這部分可以適當忽略。因為我們的通信數據並沒有那么復雜,而且大多數時候我們都會用socket,TCP/IP的方式進行通信了,實際上已經少了很多工作,所以也就是在其一些高級平台上開發並不需要你太了解底層。這樣就開發的就相當於只用開發應用層協議,定義一個自己開發功能相關的協議,而可以忽略了一些TCP/IP那些協議幫你做過的工作。如果是純底層開始那考慮的東西就比較多了。

3.3.1.參考協議

借鑒前面的一些協議,不過這里的協議其實是應用層的協議。前面也說了,所以中間省略了一些特定策略的,沒必要做TCP/IP協議族里面那些那么復雜,但是真如果有需要還是按目的添加一些參考的協議,增加對應層的策略來解決,但還是按照上下兩層提供接口的原則。

大概簡單畫了一下參考的組成,主要還是針對總線的單片機通信。其實中間有很多也可以是不需要的,具體見自己的應用需求,進行刪減和增加。

這里寫圖片描述

前導碼可以按借鑒一下以太幀的前導碼,主要的是那個01交替,可以容易區分受到的電磁干擾。同時后面可以加校驗,驗證整段數據。

地址這里仿數據鏈路層和網絡層的地址以及傳輸層的端口,為了確定接受發送雙方。但如果是一對一可以省略,同時如果沒特殊需要,源地址可以省略。同時把地址放前面,如果不是自己對應的地址數據不處理也可以加快速度。

數據長度參照網絡層,來標識數據長度,也可以用來驗證數據是否有丟失。

序號和確認應答,這里主要參照網絡層,防止有重復發送或者數據丟失的問題,數據丟失好理解,數據重復發送,有時候在有些超時重發或者接受錯誤重發很常見。

標識可以區分數據的不同類型,如果沒有那么多控制功能,可以把功能和應答號都混在一起。

數據包分塊的問題主要針對的是數據長度過大,單幀發送不能夠完全放下的問題。現在是把數據包分塊的放在了后面。但其實如果按照通信的原則這個還是屬於數據鏈路層的應該解決的問題(不同的通信方式對應的MTU不一致),應該放在前面,這樣可以讓應用層不要關注底層的事情。單如果在一些嵌入式的簡單應用中,往往收發雙方的數據鏈路是一致(如果不一致,估計由模塊里的協議棧已經幫你統一成一致了),但有的時候數據長度還是大於一次發送的長度(或者那個協議棧沒做之類的處理),這時候就需要將發送的數據拆包和合包了。這時候放在這個地方,相當於讓應用層來處理這些事情。結合標識,可以得到完整的數據。其實也是為了防止有的標准一次發送數據太小的問題。

數據校驗的話可以看自己的需求,如果覺得數據傳輸很穩定可以不用加= =,不過這里的數據校驗也是包括幾個層次的。比如(硬件干擾/路由器自身的問題之類)的錯誤,此外還有一些惡意篡改(如果數據重要),可以在應用HASH校驗驗證數據的完整性等。同時也可以使用一些加密手段防止數據內容被截取。

注:如果考慮可拓展性,省略的部分可以用保留來填充,增加靈活性。

3.3.2.透明傳輸

另外補充一下透明傳輸的知識。我之前忘記在那本書上看到了,我只記得自己截了圖,下面放上圖。

這里寫圖片描述

透明傳輸可以把關鍵部分從你的數據中排除,這樣更加清晰了數據的界限,這樣也可以減輕程序的負擔。之前記得有人問過我,數據校驗應該是部分數據還是全部數據。如果用了透明傳輸那么結果就很明顯了:肯定是先校驗全部數據,在進行處理數據。

3.3.3.程序處理

協議處理在程序中的處理表現也是分層次的。以3.3.1中的自定義協議為例,像前導碼,地址,長度可以歸為一層,這一層可以保證數據內容的正確性和接受地址的正確性;確認序列號,確認應答則控制數據傳輸過程中的可靠性。后面的標識,數據分包和數據內容則可以歸為應用的內容。

3.3.4.協議的內容

協議的內容是由自己的應用需要傳輸的數據自定義的。定義的自由度比較高,只要通信雙方按相同的規定裝數據和取數據就可以了。

單片機對通信的常見處理方式

詳見下篇。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM