1. 程式人生 > >從零開始的鐳射通訊(第1章 協議棧)——3、提取資料包

從零開始的鐳射通訊(第1章 協議棧)——3、提取資料包

從零開始的鐳射通訊(第1章 協議棧)——3、提取資料包

github

https://github.com/HaHaHaHaHaGe/mynetstack

簡介

資料包的提取其實原理並不複雜,就像拼積木一樣,見下圖:
在這裡插入圖片描述
這些字是我隨便打出來的,現在這串字串中,我說包含了三個資料包,需要提取出來
規則如下:
碰到數字:1234 代表後面的將是需要提取的資料
具體提取幾個呢,提取1234後面那個數字的個數
如:12345關懷和分化.
1234是開頭
5是提取的個數
後面的5個字就是待提取的資料
1234叫做 包頭
5叫做 資料長度

這是最簡單的情況,但是實際應用中會有些複雜,

首先我們要知道,在傳輸資料的時候,任何資料都可能被傳輸
也就是說我現在定義:若遇到1234則代表後面的將是需要提取的資料
但若傳輸的資料中恰好包含1234會怎麼樣呢?
在這裡插入圖片描述
就像這個樣子,處理肯定會出現錯誤,所以我們需要對原始資料進行一下轉化比如在每個資料面前增加一個符號’/’
在這裡插入圖片描述

其次我們知道在實際應用中,難免會有干擾
有干擾就意味著很可能資料傳輸出現錯誤
原本傳送的是1110接受端接收到的可能就變成1100了

所以在此基礎上還需要增加校驗,也就是說有專門的一個數來表示這段資料是不是正確的
在這裡插入圖片描述
到現在為止,一個比較可靠的基本資料包結構就完成了

當然在實際應用中我們不會直接使用字元去傳輸資料,更不會使用字元’/'去分割資料,這樣做太浪費資源了
那麼我們會怎麼做呢?
在這裡插入圖片描述

這是擷取開頭的一段真實資料包,首先0xff 0xff 0xff 0xff是資料包頭,00 00 04 00是資料長度 ,1F 2A 56 01 是CRC32 校驗,對包頭、資料長度、資料進行校驗,後面的就是資料了。

但是不知有沒有發現’/'是怎麼實現的呢?
實際上後面的所有的資料都是已經進行過處理的,它們的第8位恆為零,這就保證永遠不可能出現0xFF,哪怕由於干擾出現了0xFF 那麼連續出現四個0xFF的概率微乎其微,但是這種做法也會增加額外的傳輸負擔,比如若我想要傳輸56個位元組,那麼由於第八位已經被設定位固定0 所以我只能往後移一位,去佔用下一個位元組的空間。以此類推,到最後,真正傳輸的位元組就會變成:
(56*8)/7 = 64
最終我們原始資料從56位元組,變成了64位元組

函式說明

有關資料包提取的檔案在\mynetstack\Source\BasicDataStream\inc 與\mynetstack\Source\BasicDataStream\src 中
名稱為 packeg_taken.c 與 packeg_taken.h

注:程式還在更新,以GITHUB為準

/*
從拼接的兩段陣列中尋找正確的資料包
資料包格式:
-------------------------------------------------------
0-3		4-7		8-11	12-N
包頭	資料長	CRC32	資料
-------------------------------------------------------
入口引數:
src1:第一個陣列
src2:第二個陣列
len1:第一個陣列大小
len2:第二個陣列大小
rdata_1:返回資料的第一指標
rdata_2:返回資料的第二指標
rlen_1:返回資料第一指標指向的資料段長度
rlen_2:返回資料第二指標指向的資料段長度
stop_ptr:返回停止查詢的位置(被阻斷查詢的原因包括:成功找到資料包,找到損壞資料包,找到截斷資料包)
返回值:
是否找到資料包
*/
u8 search_packeg(u8*src1, u8*src2, u32 len1, u32 len2, u8**rdata_1, u8**rdata_2, u32*rlen_1, u32*rlen_2, u8** stop_ptr);


/*
從拼接的兩段陣列中尋找正確的資料包並進行7bit->8bit轉化
重新分配記憶體並儲存資料
src1:第一個陣列
src2:第二個陣列
len1:第一個陣列大小
len2:第二個陣列大小
返回值:
如果沒有正確資料包返回NULL_PTR
否則返回新分配的記憶體地址(指向轉化完畢的資料包)
*/
u8* unpacking(u8* src1, u8* src2, u32 len1, u32 len2);