如何自定義一個通訊協議
借鑑簡單的OSI和TCP/IP通訊模型來討論如何自定義一個適應自己的通訊協議
1.前言
在物聯網的通訊中,很多地方需要自定義協議。但考慮到平時工作中接觸到的自定義協議,都或多或少存在一些問題和缺陷。所以想借鑑之前看過的書上的知識以及一些國際標準的協議,來簡單談談如何設計一個自定義通訊協議,並且通訊方都遵守這個協議,並如何談談根據自己的需求對協議進行簡化。
除此之外,考慮到後面可能不太會接觸這一塊,所以可能是一次集中性的大清理,後面可能會整理一下底層(微控制器)上一般如何處理資料接受傳送的問題,大概會以lwip為例。
收集的資料會有些不全,如果有什麼比較特別的協議可以在評論指出。下面也是按我自己對這個協議理解的角度來講。為了節省篇幅著重點,中間會省去一些基本的概念。
這裡會省去一些通訊的基本概念,著重分析協議,分析每層的目的和協議組成,不分析原理。
這裡補充一點,也是突然上次有人和我說我才想起來,除了我們用相互規定的資料流來表示內容外,還有一種協議的表示方法:可以用字串解析,這種可以參考HTTP沒什麼太多需要解釋的。只不過字串的內容和方式通訊方自定義。不過個人認為這種方式對嵌入式來說沒太多必要,太浪費有限的頻寬,同時解析速度也很慢。不過就算是HTTP的下面層也是TCP,IP資料鏈路之類的,依然是要通過資料流的層次上進行包裝,只是對應用層的解析上比較直觀罷了。
2.經典的OSI七層模型
這裡首先以經典的OSI七層模型介紹整個通訊從物理層到應用層的的層次分層。分層有助於分離出不同層的處理任務和職責,不同層之間通過介面由下一層向上一層提供服務。此外,分層設計的也會過分的模組化,使處理變得繁重。
下面是模型的圖示:
這個模型分的很細,中間增加了很多保證速度,資料可靠性,安全等的機制。在我們應用的時候,根據需求不同,有著不同的側重點。有的時候需要的只是一些簡單的資料傳輸功能,有的時候我們藉助了硬體模組(模組自身已經實現了協議),或者需要實現協議棧,每種還需要根據結合情況,制定的協議有所不同。
從很多通訊模型中都不難看出,其實基本都逃不出這個模型,他們很多都是根據自己的需要在模型的基礎上做些刪減和簡化。
2.1.TCP/IP模型解析
2.1.1.整體介紹
TCP/IP是將OSI模型進行部分的簡化,將7層模型壓縮為4層模型。不過兩者的側重點不太一樣。OSI是列出了通訊的基本協議,以及具體如何分層,劃分職責。TCP/IP則側重具體協議的實現。
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.協議的內容
協議的內容是由自己的應用需要傳輸的資料自定義的。定義的自由度比較高,只要通訊雙方按相同的規定裝資料和取資料就可以了。
微控制器對通訊的常見處理方式
詳見下篇。。。