LengthFieldBasedFrameDecoder解析

解碼器LengthFieldBasedFrameDecoder, 從名字上可以猜測出來, 它是基於長度的解碼器.

Netty從TCP緩衝區中讀取字節, 把這些字節交給LengthFieldBasedFrameDecoder進行解碼, 解碼的操作是根據設定的規則, 根據規則, 從字節中解碼出來有意義的數據, 然後把數據再交給後續的Handler處理.

接下來看下, 它是如何根據規則解碼的.

 

 


在這裏插入圖片描述如上圖, 從網絡中讀取到的數據是基於流的, 而且是有方向的. 然而數據是沒有邊界的, 不知道從哪兒到哪兒是一個完整的數據, 下一個數據又是從哪個到哪個. 因此應用層需要設定規則, 根據規則就可以知道數據的邊界在哪兒.

 

 


在這裏插入圖片描述
如上圖, 便是根據設定的規則, 就可以’篩選’出來真正有意義的數據(data)在哪個. 而且允許每個data的長度是不一樣大小.

那麼就要說下這個規則是什麼了. 規則是由4個主要的屬性構成, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip. 通過一個數據塊爲例介紹這4個屬性.

 

 


在這裏插入圖片描述如上圖, 從紅色箭頭指向的位置開始讀取數據.lengthFieldOffset表示長度字段的偏移量, 經過lengthFieldOffset之後, 箭頭指向了下一個位置. 如果lengthFieldOffset=3, 那麼箭頭需要向右邊走3個字節.

 

 


在這裏插入圖片描述接下來, lengthFieldLength表示長度字段的長度(好繞口). 如果lengthFieldLength=4, 那麼就會從上圖紅色位置向後讀取4個字節, 把4個字節裏面的內容作爲真正data的長度. 而且lengthFieldLength的取值不是任意的, 它只能取值1,2,3,4,8. 具體原因後面的源碼會說明.

 

 


在這裏插入圖片描述如上圖, 假如lengthFieldLength=4, 讀取4個字節的內容是0x00000010(十六進制表示), 十進制就是16, 也就是說, 數據data的長度是16個字節. 但是這裏稍等下, 需要介紹下一個關鍵屬性.

lengthAdjustment表示長度調整. 調整什麼呢? 還是要說下lengthFieldLength. lengthFieldLength裏面的內容是16, 雖然這個16表示長度, 但是它是表示真正數據data的長度,還是表示整個的長度呢, 或者其他呢. 因此要想真正表示真正數據data的長度, 必須用lengthFieldLength的內容值+lengthAdjustment的值. 如果lengthAdjustment=-5, 也就是用16+(-5)=11, 即從上圖紅色位置繼續向後讀取11個字節才能真正的把數據讀取完整, 讀取少了或多了都不行.

到這裏, 已經把一個完整的數據塊讀取完成了. 但是呢, 真正表示業務數據的內容是data部分.我們不想要前面的lengthFieldOffset和lengthFieldLength部分,這裏就需要使用initialBytesToStrip. 它表示跳過多少字節. 如果initialBytesToStrip=7, 那麼就是說要跳過7個字節, 把剩餘部分傳給下游的Handler繼續處理.

 

 


在這裏插入圖片描述以上就是4個主要屬性的解釋, 從源碼中拿一個具體的’案例’再溫習下.

 

 


在這裏插入圖片描述
從最左邊開始讀取數據, lengthFieldOffset=1, 那麼向後讀取1個字節, lengthFieldLength=2, 向後讀取2個字節, 讀取到的內容是0x0010(十六進制), 十進制就是16, 由於lengthAdjustment=-3, 因此16+(-3)=13, 於是繼續向後讀取13個字節. 就會把0xFE和"HELLO, WORLD"這13個字節讀取到. 到目前爲止, 讀取到的內容是0xCA0010FE和"HELLO, WORLD"共16個字節. 又initialBytesToStrip=3, 因此從16個字節的開頭跳過3個字節, 跳過了0xCA0010這3個字節, 最後剩下0xFE和"HELLO, WORLD"傳給了下游的Handler.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章