Buffers 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.
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" | +--------+----------------+ +--------+----------------+
Because we can get the length of the content by calling
Buffer#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" | +--------+----------------+ +----------------+
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" | +--------+----------------+ +--------+----------------+
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" | +----------+----------+----------------+ +----------+----------+----------------+
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" | +----------+----------+----------------+ +----------+----------+----------------+
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" | +------+--------+------+----------------+ +------+----------------+
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" | +------+--------+------+----------------+ +------+----------------+
LengthFieldPrepender
| Modifier and Type | Field and Description |
|---|---|
| private final ByteOrder | |
| private long | |
| private int | |
| private final boolean | |
| private final int | |
| private final int | |
| private final int | |
| private final int | |
| private final int | |
| private final int | |
| private long |
| Access | Constructor and Description |
|---|---|
| public | LengthFieldBasedFrameDecoder(int
the maximum length of the frame. If the length of the frame is
greater than this value, maxFrameLength, int TooLongFrameException will be
thrown.the offset of the length field lengthFieldOffset, int the length of the length field lengthFieldLength)Creates a new instance. |
| public | LengthFieldBasedFrameDecoder(int
the maximum length of the frame. If the length of the frame is
greater than this value, maxFrameLength, int TooLongFrameException will be
thrown.the offset of the length field lengthFieldOffset, int the length of the length field lengthFieldLength, int the compensation value to add to the value of the length field lengthAdjustment, int the number of first bytes to strip out from the decoded frame initialBytesToStrip)Creates a new instance. |
| public | LengthFieldBasedFrameDecoder(int
the maximum length of the frame. If the length of the frame is
greater than this value, maxFrameLength, int TooLongFrameException will be
thrown.the offset of the length field lengthFieldOffset, int the length of the length field lengthFieldLength, int the compensation value to add to the value of the length field lengthAdjustment, int the number of first bytes to strip out from the decoded frame initialBytesToStrip, boolean If true, a failFast)TooLongFrameException is 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, a TooLongFrameException
is thrown after the entire frame that exceeds maxFrameLength
has been read.Creates a new instance. |
| public | LengthFieldBasedFrameDecoder(ByteOrder
the byteOrder, int ByteOrder of the length fieldthe maximum length of the frame. If the length of the frame is
greater than this value, maxFrameLength, int TooLongFrameException will be
thrown.the offset of the length field lengthFieldOffset, int the length of the length field lengthFieldLength, int the compensation value to add to the value of the length field lengthAdjustment, int the number of first bytes to strip out from the decoded frame initialBytesToStrip, boolean If true, a failFast)TooLongFrameException is 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, a TooLongFrameException
is thrown after the entire frame that exceeds maxFrameLength
has been read.Creates a new instance. |
| Modifier and Type | Method and Description |
|---|---|
| protected final void | decode(ChannelHandlerContext
the ctx, Buffer ChannelHandlerContext which this ByteToMessageDecoder belongs tothe in)Buffer from which to read dataImplements abstract io. Buffer to another.
|
| protected Object | decode0(ChannelHandlerContext
the ctx, Buffer ChannelHandlerContext which this ByteToMessageDecoder belongs tothe buffer)Buffer from which to read dataCreate a frame out of the |
| private void | |
| protected Buffer | extractFrame(ChannelHandlerContext ctx, Buffer buffer, int length)
Extract the sub-region of the specified buffer. |
| private static void | failOnFrameLengthLessThanInitialBytesToStrip(Buffer buffer, int frameLength, int initialBytesToStrip)
|
| private static void | failOnFrameLengthLessThanLengthFieldEndOffset(Buffer buffer, long frameLength, int lengthFieldEndOffset)
|
| private void | |
| private void | |
| private static void | |
| protected long | getUnadjustedFrameLength(Buffer buffer, int offset, int length, ByteOrder byteOrder)
Decodes the specified region of the buffer into an unadjusted frame length. |
| private void |
| byteOrder | back to summary |
|---|---|
| private final ByteOrder byteOrder | |
| bytesToDiscard | back to summary |
|---|---|
| private long bytesToDiscard | |
| currentFrameLength | back to summary |
|---|---|
| private int currentFrameLength | |
| failFast | back to summary |
|---|---|
| private final boolean failFast | |
| initialBytesToStrip | back to summary |
|---|---|
| private final int initialBytesToStrip | |
| lengthAdjustment | back to summary |
|---|---|
| private final int lengthAdjustment | |
| lengthFieldEndOffset | back to summary |
|---|---|
| private final int lengthFieldEndOffset | |
| lengthFieldLength | back to summary |
|---|---|
| private final int lengthFieldLength | |
| lengthFieldOffset | back to summary |
|---|---|
| private final int lengthFieldOffset | |
| maxFrameLength | back to summary |
|---|---|
| private final int maxFrameLength | |
| tooLongFrameLength | back to summary |
|---|---|
| private long tooLongFrameLength | |
| LengthFieldBasedFrameDecoder | back to summary |
|---|---|
| public LengthFieldBasedFrameDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength) Creates a new instance.
| |
| LengthFieldBasedFrameDecoder | back to summary |
|---|---|
| public LengthFieldBasedFrameDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) Creates a new instance.
| |
| LengthFieldBasedFrameDecoder | back to summary |
|---|---|
| public LengthFieldBasedFrameDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) Creates a new instance.
| |
| LengthFieldBasedFrameDecoder | back to summary |
|---|---|
| public LengthFieldBasedFrameDecoder(ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) Creates a new instance.
| |
| decode | back to summary |
|---|---|
| protected final void decode(ChannelHandlerContext ctx, Buffer in) throws Exception Implements abstract io. Doc from io. Decode the from one
| |
| decode0 | back to summary |
|---|---|
| protected Object decode0(ChannelHandlerContext ctx, Buffer buffer) throws Exception Create a frame out of the
| |
| discardTooLongFrame | back to summary |
|---|---|
| private void discardTooLongFrame(Buffer in) | |
| extractFrame | back to summary |
|---|---|
| protected Buffer extractFrame(ChannelHandlerContext ctx, Buffer buffer, int length) Extract the sub-region of the specified buffer. This method must modify the state of the buffer to continue
after the frame (e.g. by splitting the buffer or by increasing | |
| failOnFrameLengthLessThanInitialBytesToStrip | back to summary |
|---|---|
| private static void failOnFrameLengthLessThanInitialBytesToStrip(Buffer buffer, int frameLength, int initialBytesToStrip) | |
| failOnFrameLengthLessThanLengthFieldEndOffset | back to summary |
|---|---|
| private static void failOnFrameLengthLessThanLengthFieldEndOffset(Buffer buffer, long frameLength, int lengthFieldEndOffset) | |
| failOnLengthExceeded | back to summary |
|---|---|
| private void failOnLengthExceeded(long frameLength) | |
| failOnLengthExceededIfNecessary | back to summary |
|---|---|
| private void failOnLengthExceededIfNecessary(boolean firstDetectionOfTooLongFrame) | |
| failOnNegativeLengthField | back to summary |
|---|---|
| private static void failOnNegativeLengthField(Buffer buffer, long frameLength, int lengthFieldEndOffset) | |
| getUnadjustedFrameLength | back to summary |
|---|---|
| protected long getUnadjustedFrameLength(Buffer buffer, int offset, int length, ByteOrder byteOrder) 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.
| |
| handleFrameLengthExceeded | back to summary |
|---|---|
| private void handleFrameLengthExceeded(Buffer buffer, long frameLength) | |