無論是網路UDP封包或RS232的串列資料,它們的傳輸不保證內容順序及資料是正確的,
因此若要實作資料驗證機制的話,最基本的封包(Package或Frame)結構定義如下表:
起始字 | 資料長度 | 資料 | 檢查碼 |
1 byte | 2 bytes | N bytes | 1 bytes |
1. 起始字: 如固定以0xAB開頭
2. 資料長度: 代表後面資料的陣列長度,通常low byte在前,high byte在後地組成2個bytes。
3. 資料: 一個符合前面長度的byte[]陣列,有可能是0長度。
4. 檢查碼: 通常是從資料長度byte至資料陣列的最後一個byte作xor sum。
由於接收資料的socket或rs232 reader,每次事件觸發可能只收到破碎的片段資料
因此必須準備一個自訂Queue來累績存放讀取buffer進來的raw data,
當Queue的長度大於一個封包定義的最小長度時,即進行Queue的Parsing工作。
從Queue映射出一個Shadow Array(固定長度),然後使用一個loop來比對起始字
接著取得其資料長度(Data Length)。這兩個代表資料長度的bytes可能是錯誤的值,
因此要檢查其宣稱的長度值,是否在封包定義最小長度與整個映射array長度之間。
若是,則依Data Length值跳至該封包最後一個byte作checksum驗證,若正確則是有效封包區段,
直接作長度跳躍去驗證下一個封包片段起始字。
反之,若Data Length及checksum檢查失敗,則array position加1繼續比對起始字。
當中值得注意的是,當checksum失敗的話代表其區域內的bytes值都不可靠,
因此即使Data Length所宣稱值符合在Array範圍內,亦不可直接作整個長度的跳躍
只能postition + 1,繼續比對下一個起始字byte。
另外,需要設定一個queue已讀取位置的read position變數,記錄checksum失敗時的讀取位置,
避免重複再對這些不可靠的區段作parsing。等到遇到一個有效封包結構進來時,
再一次回收這些空間,該read position變數再設為0。
以上是業界作資料驗證的邏輯原則,筆者經過千錘百鍊的資料傳輸驗證及效能除錯
基於智慧財產保障,僅提供流程邏輯,並不提供源碼分享,尚請見諒。