Netty中的LengthFieldBasedFrameDecoder解碼器

LengthFieldBasedFrameDecoder是一個基於長度解碼器, 它是Netty提供的4個解碼器中使用最廣泛的一個解碼器, RocketMQ中就是基於這個解碼器進行解碼消息的.

接下來分析下它是如何解碼消息的. 在它的類中主要有4個屬性:

<code>private final int lengthFieldOffset;
private final int lengthFieldLength;
private final int lengthAdjustment;
private final int initialBytesToStrip;/<code>


Netty中的LengthFieldBasedFrameDecoder解碼器

只有真正理解這4個屬性才能明白此解碼器的強大功能.

為了描述, 我們先把數據構造下. 假如我們要發送’你好’這兩個字, 轉成16進制就是27b0597d.

此時客戶端發送過來一串消息, 為了描述, 我們把消息轉成16進制進行講解:

0xDC00000A006327b0597d


對於上面的消息, 如何將其解碼出來’你好’兩個字呢? 即如何解碼出來27b0597d, 就要使用到LengthFieldBasedFrameDecoder解碼器, 那麼我們就要設置上面的4個屬性了.

<code>lengthFieldOffset = 1
lengthFieldLength = 3
lengthAdjustment = -4
initialBytesToStrip = 6/<code>

(之所以為什麼這幾個屬性要設置這幾個數字,而不是其他數字, 其實是由消息結構和消息長度決定的)

我們說下每個值的含義:

lengthFieldOffset = 1表示長度域的偏移量是1, 那麼從最開始向後移動1個字節, 就到了0xDC的後面位置; lengthFieldLength = 3表示長度域是3個字節, 在C的後面繼續讀取3個字節, 即讀取到了0xDC

00000A006327b0597d中的00000A, 00000A就是十進制10; lengthAdjustment = -4是調整長度, 就是用10+(-4)=6, 也就是說, 從A位置向後讀取6個字節. 我們就讀取到了0xDC00000A006327b0597d中的006327b0597d. 到目前為止, 我們總共讀取到的字節是DC00000A006327b0597d, initialBytesToStrip = 6表示在原有消息的基礎上從頭跳過6個字節, 所以最後讀取到的消息就是27b0597d, 也就是’你好’這兩個字, 當然讀取到的’你好’目前還是ByteBuf類型, 會把這個ByteBuf繼續向下傳播, 由接下來的業務解碼器將其解碼成字符串, 最後就是’你好’這兩個字了.

整體思路:

1.從消息開頭偏移lengthFieldOffset長度, 到達A位置

2.再從A位置讀取lengthFieldLength長度, 到達B位置, 內容是d

3.再從B位置讀取(d+lengthAdjustment)長度, 達到D位置

4.從消息開頭跳過initialBytesToStrip長度到達C位置

5.將C位置-D位置之間的內容傳送給接下來的處理器進行後續處理


用下面7個例子鍛鍊一下自己吧


Netty中的LengthFieldBasedFrameDecoder解碼器


Netty中的LengthFieldBasedFrameDecoder解碼器


Netty中的LengthFieldBasedFrameDecoder解碼器


Netty中的LengthFieldBasedFrameDecoder解碼器


Netty中的LengthFieldBasedFrameDecoder解碼器


Netty中的LengthFieldBasedFrameDecoder解碼器


Netty中的LengthFieldBasedFrameDecoder解碼器


分享到:


相關文章: