public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder
ByteBuf
s 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.
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" | +--------+----------------+ +--------+----------------+
ByteBuf.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" | +--------+----------------+ +----------------+
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" | +--------+----------------+ +--------+----------------+
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" | +----------+----------+----------------+ +----------+----------+----------------+
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" | +----------+----------+----------------+ +----------+----------+----------------+
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" | +------+--------+------+----------------+ +------+----------------+
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
ByteToMessageDecoder.Cumulator
ChannelHandler.Sharable
COMPOSITE_CUMULATOR, MERGE_CUMULATOR
Constructor and Description |
---|
LengthFieldBasedFrameDecoder(java.nio.ByteOrder byteOrder,
int maxFrameLength,
int lengthFieldOffset,
int lengthFieldLength,
int lengthAdjustment,
int initialBytesToStrip,
boolean failFast)
Creates a new instance.
|
LengthFieldBasedFrameDecoder(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.
|
Modifier and Type | Method and Description |
---|---|
protected java.lang.Object |
decode(ChannelHandlerContext ctx,
ByteBuf in)
Create a frame out of the
ByteBuf and return it. |
protected void |
decode(ChannelHandlerContext ctx,
ByteBuf in,
java.util.List<java.lang.Object> out)
Decode the from one
ByteBuf to an other. |
protected ByteBuf |
extractFrame(ChannelHandlerContext ctx,
ByteBuf buffer,
int index,
int length)
Extract the sub-region of the specified buffer.
|
protected long |
getUnadjustedFrameLength(ByteBuf buf,
int offset,
int length,
java.nio.ByteOrder order)
Decodes the specified region of the buffer into an unadjusted frame length.
|
actualReadableBytes, callDecode, channelInactive, channelRead, channelReadComplete, decodeLast, discardSomeReadBytes, handlerRemoved, handlerRemoved0, internalBuffer, isSingleDecode, setCumulator, setDiscardAfterReads, setSingleDecode, userEventTriggered
channelActive, channelRegistered, channelUnregistered, channelWritabilityChanged, exceptionCaught
ensureNotSharable, handlerAdded, isSharable
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
handlerAdded
public LengthFieldBasedFrameDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength)
maxFrameLength
- the maximum length of the frame. If the length of the frame is
greater than this value, TooLongFrameException
will be
thrown.lengthFieldOffset
- the offset of the length fieldlengthFieldLength
- the length of the length fieldpublic LengthFieldBasedFrameDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip)
maxFrameLength
- the maximum length of the frame. If the length of the frame is
greater than this value, TooLongFrameException
will 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 framepublic LengthFieldBasedFrameDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast)
maxFrameLength
- the maximum length of the frame. If the length of the frame is
greater than this value, TooLongFrameException
will 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, a 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.public LengthFieldBasedFrameDecoder(java.nio.ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast)
byteOrder
- the ByteOrder
of the length fieldmaxFrameLength
- the maximum length of the frame. If the length of the frame is
greater than this value, TooLongFrameException
will 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, a 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.protected final void decode(ChannelHandlerContext ctx, ByteBuf in, java.util.List<java.lang.Object> out) throws java.lang.Exception
ByteToMessageDecoder
ByteBuf
to an other. This method will be called till either the input
ByteBuf
has nothing to read when return from this method or till nothing was read from the input
ByteBuf
.decode
in class ByteToMessageDecoder
ctx
- the ChannelHandlerContext
which this ByteToMessageDecoder
belongs toin
- the ByteBuf
from which to read dataout
- the List
to which decoded messages should be addedjava.lang.Exception
- is thrown if an error occursprotected java.lang.Object decode(ChannelHandlerContext ctx, ByteBuf in) throws java.lang.Exception
ByteBuf
and return it.ctx
- the ChannelHandlerContext
which this ByteToMessageDecoder
belongs toin
- the ByteBuf
from which to read dataByteBuf
which represent the frame or null
if no frame could
be created.java.lang.Exception
protected long getUnadjustedFrameLength(ByteBuf buf, int offset, int length, java.nio.ByteOrder order)
readerIndex
, writerIndex
, and the content of the buffer.)DecoderException
- if failed to decode the specified regionprotected ByteBuf extractFrame(ChannelHandlerContext ctx, ByteBuf buffer, int index, int length)
If you are sure that the frame and its content are not accessed after
the current decode(ChannelHandlerContext, ByteBuf)
call returns, you can even avoid memory copy by returning the sliced
sub-region (i.e. return buffer.slice(index, length)).
It's often useful when you convert the extracted frame into an object.
Refer to the source code of ObjectDecoder
to see how this method
is overridden to avoid memory copy.
Copyright © 2008–2018 The Netty Project. All rights reserved.