深入netty之二自定義LengthFieldBasedFrameDecoder類

前面說到,LengthFieldBasedFrameDecoder類是我們最常用的一個粘包拆包工具,能幫我們解決95%以上的粘包拆包問題。
LengthFieldBasedFrameDecoder類能夠解決的最復(fù)雜的數(shù)據(jù)包結(jié)構(gòu)類似如下:

數(shù)據(jù)包協(xié)議示例1
數(shù)據(jù)包協(xié)議示例1

從上圖可以看出,這種協(xié)議類似“包頭1 + 包體長度 + 包頭2 + 包體”這種結(jié)構(gòu)。
這種協(xié)議結(jié)構(gòu)已經(jīng)很復(fù)雜了,但現(xiàn)實往往不盡如人意,比如有如下形式的數(shù)據(jù)協(xié)議:

數(shù)據(jù)包協(xié)議示例2
數(shù)據(jù)包協(xié)議示例2

這種數(shù)據(jù)協(xié)議結(jié)構(gòu)類似于“包頭 + 包體長度 + 包體 +包尾”。
很明顯,這種帶“包尾”的協(xié)議結(jié)構(gòu),就是LengthFieldBasedFrameDecoder類不能解決的。
因此,我們必須自定義這種協(xié)議的LengthFieldBasedFrameDecoder類。
我們通過對LengthFieldBasedFrameDecoder類進行預(yù)研,發(fā)現(xiàn)我們自定義的LengthFieldBasedFrameDecoder類不能夠通過繼承LengthFieldBasedFrameDecoder類來解決問題,只能把LengthFieldBasedFrameDecoder類的代碼拷貝過來修改。
開始的代碼如下:

public class CashboxDataLengthFieldBasedFrameDecoder extends ByteToMessageDecoder {

    private static final int TAIL_LENGTH = 7;

    private final ByteOrder byteOrder;
    private final int maxFrameLength;
    private final int lengthFieldOffset;
    private final int lengthFieldLength;
    private final int lengthFieldEndOffset;
    private final int lengthAdjustment;
    private final int initialBytesToStrip;
    private final boolean failFast;
    private boolean discardingTooLongFrame;
    private long tooLongFrameLength;
    private long bytesToDiscard;

所有的粘包拆包解碼器類,都需要繼承ByteToMessageDecoder類。
再往下,就是我們自定義的包尾長度-private static final int TAIL_LENGTH = 7;,后面都是拷貝LengthFieldBasedFrameDecoder類的代碼。
最后的修改在decode方法里:

protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
if (discardingTooLongFrame) {
    discardingTooLongFrame(in);
}

if (in.readableBytes() < lengthFieldEndOffset) {
    return null;
}

int actualLengthFieldOffset = in.readerIndex() + lengthFieldOffset;
long frameLength = getUnadjustedFrameLength(in, actualLengthFieldOffset, lengthFieldLength, byteOrder);

if (frameLength < 0) {
    failOnNegativeLengthField(in, frameLength, lengthFieldEndOffset);
}

/**
 * 增加的代碼,加上尾部的長度,作為內(nèi)容的長度。
 */
frameLength += TAIL_LENGTH;

frameLength += lengthAdjustment + lengthFieldEndOffset;

可以看到,僅有的改動就在內(nèi)容長度-frameLength上,將這個長度再加上包尾的長度,就可以了。
后面的代碼,就都是考慮原LengthFieldBasedFrameDecoder類的代碼了,在此就不再多說了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容