使用netty做tcp連接時,會遇到tcp粘包問題,通常的解決方案:1、設置固定大小的消息,每次截取固定長度的字節流;2、設置結束符如\n;3、定義消息協議,設置消息頭和消息體,在消息頭中添加表示消息長度的字段,根據長度字段截取消息。但是實現起來需要一定的經驗。而netty已經爲我們做了這部分邏輯的解決方案就是LengthFieldBasedFrameDecoder。
LengthFieldBasedFrameDecoder是基於第三種方案設計的,他的構造方法有幾個參數可以解決不同協議之間的差異問題。1、maxFrameLength 消息的最大長度
2、lengthFieldOffset 消息頭中長度字段的起始位置
3、lengthFieldLength 消息字段的長度
4、lengthAdjustment 消息修改長度 用於修改消息的長度
5、initialBytesToStrip 消息中需要丟棄的字節長度
LengthFieldBasedFrameDecoder中對消息的解析拆包主要在decode方法中,首先獲取消息長度字段的實際起始位置
int actualLengthFieldOffset = in.readerIndex() + lengthFieldOffset;
接下來獲取長度字段的值
long frameLength = getUnadjustedFrameLength(in, actualLengthFieldOffset, lengthFieldLength, byteOrder);
然後計算整個消息的長度(消息長度=消息長度字段值+消息修改長度+消息長度字段的結束位置)
frameLength += lengthAdjustment + lengthFieldEndOffset;
接下來丟棄字節
in.skipBytes(initialBytesToStrip);
最後截取新的字節數組容器ByteBuf並設置readerIndex
ByteBuf frame = extractFrame(ctx, in, readerIndex, actualFrameLength); in.readerIndex(readerIndex + actualFrameLength);