Class LengthFieldBasedFrameDecoder
java.lang.Object
io.netty.channel.ChannelHandlerAdapter
io.netty.channel.ChannelInboundHandlerAdapter
io.netty.handler.codec.ByteToMessageDecoder
io.netty.handler.codec.LengthFieldBasedFrameDecoder
- All Implemented Interfaces:
ChannelHandler, ChannelInboundHandler
- Direct Known Subclasses:
MarshallingDecoder, ObjectDecoder, TcpDnsQueryDecoder, TcpDnsResponseDecoder
A decoder that splits the received
ByteBufs dynamically by the
value of the length field in the message. It is particularly useful when you
decode a binary message which has an integer header field that represents the
length of the message body or the whole message.
LengthFieldBasedFrameDecoder has many configuration parameters so
that it can decode any message with a length field, which is often seen in
proprietary client-server protocols. Here are some example that will give
you the basic idea on which option does what.
2 bytes length field at offset 0, do not strip header
The value of the length field in this example is 12 (0x0C) which represents the length of "HELLO, WORLD". By default, the decoder assumes that the length field represents the number of the bytes that follows the length field. Therefore, it can be decoded with the simplistic parameter combination.lengthFieldOffset = 0 lengthFieldLength = 2 lengthAdjustment = 0 initialBytesToStrip = 0 (= do not strip header) BEFORE DECODE (14 bytes) AFTER DECODE (14 bytes) +--------+----------------+ +--------+----------------+ | Length | Actual Content |----->| Length | Actual Content | | 0x000C | "HELLO, WORLD" | | 0x000C | "HELLO, WORLD" | +--------+----------------+ +--------+----------------+
2 bytes length field at offset 0, strip header
Because we can get the length of the content by callingByteBuf.readableBytes(), you might want to strip the length
field by specifying initialBytesToStrip. In this example, we
specified 2, that is same with the length of the length field, to
strip the first two bytes.
lengthFieldOffset = 0 lengthFieldLength = 2 lengthAdjustment = 0 initialBytesToStrip = 2 (= the length of the Length field) BEFORE DECODE (14 bytes) AFTER DECODE (12 bytes) +--------+----------------+ +----------------+ | Length | Actual Content |----->| Actual Content | | 0x000C | "HELLO, WORLD" | | "HELLO, WORLD" | +--------+----------------+ +----------------+
2 bytes length field at offset 0, do not strip header, the length field represents the length of the whole message
In most cases, the length field represents the length of the message body only, as shown in the previous examples. However, in some protocols, the length field represents the length of the whole message, including the message header. In such a case, we specify a non-zero lengthAdjustment. Because the length value in this example message is always greater than the body length by 2, we specify -2 as lengthAdjustment for compensation.lengthFieldOffset = 0 lengthFieldLength = 2 lengthAdjustment = -2 (= the length of the Length field) initialBytesToStrip = 0 BEFORE DECODE (14 bytes) AFTER DECODE (14 bytes) +--------+----------------+ +--------+----------------+ | Length | Actual Content |----->| Length | Actual Content | | 0x000E | "HELLO, WORLD" | | 0x000E | "HELLO, WORLD" | +--------+----------------+ +--------+----------------+
3 bytes length field at the end of 5 bytes header, do not strip header
The following message is a simple variation of the first example. An extra header value is prepended to the message. lengthAdjustment is zero again because the decoder always takes the length of the prepended data into account during frame length calculation.lengthFieldOffset = 2 (= the length of Header 1) lengthFieldLength = 3 lengthAdjustment = 0 initialBytesToStrip = 0 BEFORE DECODE (17 bytes) AFTER DECODE (17 bytes) +----------+----------+----------------+ +----------+----------+----------------+ | Header 1 | Length | Actual Content |----->| Header 1 | Length | Actual Content | | 0xCAFE | 0x00000C | "HELLO, WORLD" | | 0xCAFE | 0x00000C | "HELLO, WORLD" | +----------+----------+----------------+ +----------+----------+----------------+
3 bytes length field at the beginning of 5 bytes header, do not strip header
This is an advanced example that shows the case where there is an extra header between the length field and the message body. You have to specify a positive lengthAdjustment so that the decoder counts the extra header into the frame length calculation.lengthFieldOffset = 0 lengthFieldLength = 3 lengthAdjustment = 2 (= the length of Header 1) initialBytesToStrip = 0 BEFORE DECODE (17 bytes) AFTER DECODE (17 bytes) +----------+----------+----------------+ +----------+----------+----------------+ | Length | Header 1 | Actual Content |----->| Length | Header 1 | Actual Content | | 0x00000C | 0xCAFE | "HELLO, WORLD" | | 0x00000C | 0xCAFE | "HELLO, WORLD" | +----------+----------+----------------+ +----------+----------+----------------+
2 bytes length field at offset 1 in the middle of 4 bytes header, strip the first header field and the length field
This is a combination of all the examples above. There are the prepended header before the length field and the extra header after the length field. The prepended header affects the lengthFieldOffset and the extra header affects the lengthAdjustment. We also specified a non-zero initialBytesToStrip to strip the length field and the prepended header from the frame. If you don't want to strip the prepended header, you could specify 0 for initialBytesToSkip.lengthFieldOffset = 1 (= the length of HDR1) lengthFieldLength = 2 lengthAdjustment = 1 (= the length of HDR2) initialBytesToStrip = 3 (= the length of HDR1 + LEN) BEFORE DECODE (16 bytes) AFTER DECODE (13 bytes) +------+--------+------+----------------+ +------+----------------+ | HDR1 | Length | HDR2 | Actual Content |----->| HDR2 | Actual Content | | 0xCA | 0x000C | 0xFE | "HELLO, WORLD" | | 0xFE | "HELLO, WORLD" | +------+--------+------+----------------+ +------+----------------+
2 bytes length field at offset 1 in the middle of 4 bytes header, strip the first header field and the length field, the length field represents the length of the whole message
Let's give another twist to the previous example. The only difference from the previous example is that the length field represents the length of the whole message instead of the message body, just like the third example. We have to count the length of HDR1 and Length into lengthAdjustment. Please note that we don't need to take the length of HDR2 into account because the length field already includes the whole header length.lengthFieldOffset = 1 lengthFieldLength = 2 lengthAdjustment = -3 (= the length of HDR1 + LEN, negative) initialBytesToStrip = 3 BEFORE DECODE (16 bytes) AFTER DECODE (13 bytes) +------+--------+------+----------------+ +------+----------------+ | HDR1 | Length | HDR2 | Actual Content |----->| HDR2 | Actual Content | | 0xCA | 0x0010 | 0xFE | "HELLO, WORLD" | | 0xFE | "HELLO, WORLD" | +------+--------+------+----------------+ +------+----------------+
- See Also:
-
Nested Class Summary
Nested classes/interfaces inherited from class ByteToMessageDecoder
ByteToMessageDecoder.CumulatorNested classes/interfaces inherited from interface ChannelHandler
ChannelHandler.Sharable -
Field Summary
Fields inherited from class ByteToMessageDecoder
COMPOSITE_CUMULATOR, MERGE_CUMULATOR -
Constructor Summary
ConstructorsConstructorDescriptionLengthFieldBasedFrameDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength) Creates a new instance.LengthFieldBasedFrameDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) Creates a new instance.LengthFieldBasedFrameDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) Creates a new instance.LengthFieldBasedFrameDecoder(ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) Creates a new instance. -
Method Summary
Modifier and TypeMethodDescriptionprotected Objectdecode(ChannelHandlerContext ctx, ByteBuf in) Create a frame out of theByteBufand return it.protected final voiddecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) Decode the from oneByteBufto an other.protected ByteBufextractFrame(ChannelHandlerContext ctx, ByteBuf buffer, int index, int length) Extract the sub-region of the specified buffer.protected longgetUnadjustedFrameLength(ByteBuf buf, int offset, int length, ByteOrder order) Decodes the specified region of the buffer into an unadjusted frame length.Methods inherited from class ByteToMessageDecoder
actualReadableBytes, callDecode, channelInactive, channelRead, channelReadComplete, decodeLast, discardSomeReadBytes, handlerRemoved, handlerRemoved0, internalBuffer, isSingleDecode, setCumulator, setDiscardAfterReads, setSingleDecode, userEventTriggeredMethods inherited from class ChannelInboundHandlerAdapter
channelActive, channelRegistered, channelUnregistered, channelWritabilityChanged, exceptionCaughtMethods inherited from class ChannelHandlerAdapter
ensureNotSharable, handlerAdded, isSharableMethods inherited from class Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface ChannelHandler
handlerAdded
-
Constructor Details
-
LengthFieldBasedFrameDecoder
public LengthFieldBasedFrameDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength) Creates a new instance.- Parameters:
maxFrameLength- the maximum length of the frame. If the length of the frame is greater than this value,TooLongFrameExceptionwill be thrown.lengthFieldOffset- the offset of the length fieldlengthFieldLength- the length of the length field
-
LengthFieldBasedFrameDecoder
public LengthFieldBasedFrameDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) Creates a new instance.- Parameters:
maxFrameLength- the maximum length of the frame. If the length of the frame is greater than this value,TooLongFrameExceptionwill be thrown.lengthFieldOffset- the offset of the length fieldlengthFieldLength- the length of the length fieldlengthAdjustment- the compensation value to add to the value of the length fieldinitialBytesToStrip- the number of first bytes to strip out from the decoded frame
-
LengthFieldBasedFrameDecoder
public LengthFieldBasedFrameDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) Creates a new instance.- Parameters:
maxFrameLength- the maximum length of the frame. If the length of the frame is greater than this value,TooLongFrameExceptionwill be thrown.lengthFieldOffset- the offset of the length fieldlengthFieldLength- the length of the length fieldlengthAdjustment- the compensation value to add to the value of the length fieldinitialBytesToStrip- the number of first bytes to strip out from the decoded framefailFast- If true, aTooLongFrameExceptionis thrown as soon as the decoder notices the length of the frame will exceed maxFrameLength regardless of whether the entire frame has been read. If false, aTooLongFrameExceptionis thrown after the entire frame that exceeds maxFrameLength has been read.
-
LengthFieldBasedFrameDecoder
public LengthFieldBasedFrameDecoder(ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) Creates a new instance.- Parameters:
byteOrder- theByteOrderof the length fieldmaxFrameLength- the maximum length of the frame. If the length of the frame is greater than this value,TooLongFrameExceptionwill be thrown.lengthFieldOffset- the offset of the length fieldlengthFieldLength- the length of the length fieldlengthAdjustment- the compensation value to add to the value of the length fieldinitialBytesToStrip- the number of first bytes to strip out from the decoded framefailFast- If true, aTooLongFrameExceptionis thrown as soon as the decoder notices the length of the frame will exceed maxFrameLength regardless of whether the entire frame has been read. If false, aTooLongFrameExceptionis thrown after the entire frame that exceeds maxFrameLength has been read.
-
-
Method Details
-
decode
protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception Description copied from class:ByteToMessageDecoderDecode the from oneByteBufto an other. This method will be called till either the inputByteBufhas nothing to read when return from this method or till nothing was read from the inputByteBuf.- Specified by:
decodein classByteToMessageDecoder- Parameters:
ctx- theChannelHandlerContextwhich thisByteToMessageDecoderbelongs toin- theByteBuffrom which to read dataout- theListto which decoded messages should be added- Throws:
Exception- is thrown if an error occurs
-
decode
Create a frame out of theByteBufand return it.- Parameters:
ctx- theChannelHandlerContextwhich thisByteToMessageDecoderbelongs toin- theByteBuffrom which to read data- Returns:
- frame the
ByteBufwhich represent the frame ornullif no frame could be created. - Throws:
Exception
-
getUnadjustedFrameLength
Decodes the specified region of the buffer into an unadjusted frame length. The default implementation is capable of decoding the specified region into an unsigned 8/16/24/32/64 bit integer. Override this method to decode the length field encoded differently. Note that this method must not modify the state of the specified buffer (e.g.readerIndex,writerIndex, and the content of the buffer.)- Throws:
DecoderException- if failed to decode the specified region
-
extractFrame
Extract the sub-region of the specified buffer.
-