ChannelInboundHandlerAdapter
which decodes bytes in a stream-like fashion from one ByteBuf
to an other Message type. For example here is an implementation which reads all
readable bytes from the input ByteBuf
and create a new ByteBuf
.
public class SquareDecoder extendsByteToMessageDecoder
{@Override
public void decode(ChannelHandlerContext
ctx,ByteBuf
in, List<Object> out) throwsException
{ out.add(in.readBytes(in.readableBytes())); } }
Frame detection
Generally frame detection should be handled earlier in the pipeline by adding a DelimiterBasedFrameDecoder
, FixedLengthFrameDecoder
, LengthFieldBasedFrameDecoder
, or LineBasedFrameDecoder
.
If a custom frame decoder is required, then one needs to be careful when implementing one with ByteToMessageDecoder
. Ensure there are enough bytes in the buffer for a complete frame by checking ByteBuf.readableBytes()
. If there are not enough bytes for a complete frame, return without modifying the reader index to allow more bytes to arrive.
To check for complete frames without modifying the reader index, use methods like ByteBuf.getInt(int)
. One MUST use the reader index when using methods like ByteBuf.getInt(int)
. For example calling in.getInt(0) is assuming the frame starts at the beginning of the buffer, which is not always the case. Use in.getInt(in.readerIndex()) instead.
Pitfalls
Be aware that sub-classes of ByteToMessageDecoder
MUST NOT annotated with @Sharable
.
Some methods such as ByteBuf.readBytes(int)
will cause a memory leak if the returned buffer is not released or added to the out List
. Use derived buffers like ByteBuf.readSlice(int)
to avoid leaking memory.