所謂通信協議是指通信雙方的一種約定。約定包括對數據格式、同步方式、傳送速度、傳送步驟、檢糾錯方式以及控制字符定義等問題做出統一規定,通信雙方必須共同遵守,屬於OSI七層參考模型中的數據鏈路層。目前,采用的通信協議有兩類:異步協議和同步協議。
異步協議為起止式異步協議。異步通信是按字符傳輸的,每傳輸一個字符,就用起始位來通知收方,以此來重新核對收發雙方同步。若接收設備和發送設備兩者的時鍾頻率略有偏差,這也不會因偏差的累積而導致錯位,加之字符之間的空閑位也為這種偏差提供一種緩沖,所以異步串行通信的可靠性高。但由於要在每個字符的前后加上起始位和停止位這樣一些附加位,使得傳輸效率變低了,只有約80%。因此,起止協議一般用在數據速率較慢的場合(小於19.2kbit/s)。同步協議分為面向字符和面向比特以及面向字節計數三種。在高速傳送時,一般要采用同步協議。
總的來說,通訊協議就是通訊雙方共同遵循的一套規則,定義協議的原則是盡可能的簡單以提高傳輸率,盡可能的具有安全性保證數據傳輸完整正確。基於這2點規則,我們一個通訊協議應該是這樣的:頭+數據長度+數據正文+校驗
例如:AA 44 05 01 02 03 04 05 EA
這里我假設的一條數據,協議如下:
數據頭: AA 44
數據長度: 05
數據正文: 01 02 03 04 05
校驗: EA
一般數據的校驗,都會采用常用的方式,CRC16,CRC32,Xor。
有的數據安全要求高的,不允許丟包的,可能還要加入重發機制或是加入數據恢復算法,在校驗后根據前面數據添加恢復字節流以恢復數據。我這里采用的是簡單的異或校驗,包含數據頭的所有字節,依次異或得到的。
協議很簡單,我也認為分析協議是很簡單的事情,下面我們就如何分析協議來實際的結合c#看一下。
er…再等等,在我們實際開始編碼之前,還有一個規則需要了解,我們有了通訊協議,如何結合串口的協議來分析,需要關心什么呢?一般就是3個問題:
1、如何緩存收到的所有數據
2、如何找到一條完整數據
3、如何分析數據
如何緩存收到的所有數據?
如果分的更詳細一點,比如針對緩存收到的所有數據這個問題,我們想到最高效的辦法就是順序表,也就是數組,但數組的操作比較復雜,當你使用完一條數據后,用過的需要移除;新數據如果過多的時候,緩存過大需要清理;數據搬移等等,很有可能一個不小心就會丟數據導致軟件出些莫名其妙的小問題。個人建議,使用List<byte>,內部是數組方式實現,每次數據不足夠的時候會擴容1倍,數據的增刪改都已經做的很完善了。不會出現什么小問題。
如何找到一條完整數據?
如何找到完整數據呢?就我們例子的這個協議,首先在緩存的數據中找AA 44,當我們找到后,探測后面的字節,發現是05,然后看緩存剩下的數據長度是否足夠,不足夠就不用判斷,減少時間消耗,如果剩余數據>=6個(包含1個字節的校驗),我們就算一個校驗,看和最后的校驗是否一致。
如何分析數據?
分析數據:鑒於網絡的開放性,我無法確定讀者對c#的了解程度,介紹一下,常用的方式就是BitConvert.ToInt32這一系列的方法,把連續的字節(和變量長度一樣)讀取並轉換為對應的變量。c++下使用memcpy,或直接類型轉換后進行值拷貝,vb6下使用CopyMemory這個api。
校驗:前面說過了。完整性判斷的時候需要和校驗對比,大多系統都不太嚴格,不支持重發,所以數據錯誤就直接丟棄。導致數據錯誤的原因很多,比如電磁干擾導致數據不完整或錯誤、硬件驅動效率不夠導致數據丟失、我們的軟件緩存出錯等。這些軟件因素數據系統錯誤,需要修改,但是電磁干擾么,有這個可能的。雖然很少。
我們在回顧一下,一般二進制格式數據就是這樣分析,分析數據長度是否足夠,找到數據頭,數據長度,校驗,然后分析。
