Class ByteToMessageDecoder
- All Implemented Interfaces:
io.netty.channel.ChannelHandler
,io.netty.channel.ChannelInboundHandler
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 ChannelHandler.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.
-
Nested Class Summary
Nested classes/interfaces inherited from interface io.netty.channel.ChannelHandler
io.netty.channel.ChannelHandler.Sharable
-
Constructor Summary
ConstructorsModifierConstructorDescriptionprotected
ByteToMessageDecoder
(io.netty.buffer.ByteBufAllocator cumulationAllocator) Create a new instance. -
Method Summary
Modifier and TypeMethodDescriptionvoid
channelInactive
(io.netty.channel.ChannelHandlerContext ctx) void
channelRead
(io.netty.channel.ChannelHandlerContext ctx, Object msg) void
channelReadComplete
(io.netty.channel.ChannelHandlerContext ctx) protected void
Resets cumulation.protected abstract void
decode
(io.netty.channel.ChannelHandlerContext ctx, io.netty.buffer.ByteBuf in) Decode the from oneByteBuf
to an other.protected void
decodeLast
(io.netty.channel.ChannelHandlerContext ctx, io.netty.buffer.ByteBuf in) Is called one last time when theChannelHandlerContext
goes in-active.final void
handlerRemoved
(io.netty.channel.ChannelHandlerContext ctx) protected void
handlerRemoved0
(io.netty.channel.ChannelHandlerContext ctx) Gets called after theByteToMessageDecoder
was removed from the actual context and it doesn't handle events anymore.protected io.netty.buffer.ByteBuf
swapAndCopyCumulation
(io.netty.buffer.ByteBuf cumulation, io.netty.buffer.ByteBuf in) Swap the existingcumulation
ByteBuf
for a newByteBuf
and copyin
.void
userEventTriggered
(io.netty.channel.ChannelHandlerContext ctx, Object evt) Methods inherited from class io.netty.channel.ChannelInboundHandlerAdapter
channelActive, channelRegistered, channelUnregistered, channelWritabilityChanged, exceptionCaught
Methods inherited from class io.netty.channel.ChannelHandlerAdapter
ensureNotSharable, handlerAdded, isSharable
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Methods inherited from interface io.netty.channel.ChannelHandler
handlerAdded
-
Constructor Details
-
ByteToMessageDecoder
protected ByteToMessageDecoder(io.netty.buffer.ByteBufAllocator cumulationAllocator) Create a new instance.- Parameters:
cumulationAllocator
- UnpooledByteBufAllocator
used to allocate more memory, if necessary for cumulation.- Throws:
IllegalArgumentException
- if the providedcumulationAllocator
is not unpooled.
-
-
Method Details
-
handlerRemoved
public final void handlerRemoved(io.netty.channel.ChannelHandlerContext ctx) - Specified by:
handlerRemoved
in interfaceio.netty.channel.ChannelHandler
- Overrides:
handlerRemoved
in classio.netty.channel.ChannelHandlerAdapter
-
handlerRemoved0
protected void handlerRemoved0(io.netty.channel.ChannelHandlerContext ctx) Gets called after theByteToMessageDecoder
was removed from the actual context and it doesn't handle events anymore.- Parameters:
ctx
- theChannelHandlerContext
which thisByteToMessageDecoder
belongs to
-
channelRead
- Specified by:
channelRead
in interfaceio.netty.channel.ChannelInboundHandler
- Overrides:
channelRead
in classio.netty.channel.ChannelInboundHandlerAdapter
-
channelReadComplete
public void channelReadComplete(io.netty.channel.ChannelHandlerContext ctx) - Specified by:
channelReadComplete
in interfaceio.netty.channel.ChannelInboundHandler
- Overrides:
channelReadComplete
in classio.netty.channel.ChannelInboundHandlerAdapter
-
swapAndCopyCumulation
protected io.netty.buffer.ByteBuf swapAndCopyCumulation(io.netty.buffer.ByteBuf cumulation, io.netty.buffer.ByteBuf in) Swap the existingcumulation
ByteBuf
for a newByteBuf
and copyin
. This method is called when a heuristic determines the amount of unused bytes is sufficiently high that a resize / defragmentation of the bytes fromcumulation
is beneficial.ByteBuf.discardReadBytes()
is generally avoided in this method because it changes the underlying data structure. If others have slices of thisByteBuf
their view on the data will become corrupted. This is commonly a problem when processing data asynchronously to avoid blocking theEventLoop
thread.- Parameters:
cumulation
- TheByteBuf
that accumulates across socket read operations.in
- The bytes to copy.- Returns:
- the result of the swap and copy operation.
-
cumulationReset
protected void cumulationReset()Resets cumulation. -
channelInactive
public void channelInactive(io.netty.channel.ChannelHandlerContext ctx) - Specified by:
channelInactive
in interfaceio.netty.channel.ChannelInboundHandler
- Overrides:
channelInactive
in classio.netty.channel.ChannelInboundHandlerAdapter
-
userEventTriggered
public void userEventTriggered(io.netty.channel.ChannelHandlerContext ctx, Object evt) throws Exception - Specified by:
userEventTriggered
in interfaceio.netty.channel.ChannelInboundHandler
- Overrides:
userEventTriggered
in classio.netty.channel.ChannelInboundHandlerAdapter
- Throws:
Exception
-
decode
protected abstract void decode(io.netty.channel.ChannelHandlerContext ctx, io.netty.buffer.ByteBuf in) throws Exception Decode the from oneByteBuf
to an other. This method will be called till either the inputByteBuf
has nothing to read when return from this method or till nothing was read from the inputByteBuf
.- Parameters:
ctx
- theChannelHandlerContext
which thisByteToMessageDecoder
belongs toin
- theByteBuf
from which to read data- Throws:
Exception
- is thrown if an error occurs
-
decodeLast
protected void decodeLast(io.netty.channel.ChannelHandlerContext ctx, io.netty.buffer.ByteBuf in) throws Exception Is called one last time when theChannelHandlerContext
goes in-active. Which means thechannelInactive(ChannelHandlerContext)
was triggered. By default this will just calldecode(ChannelHandlerContext, ByteBuf)
but sub-classes may override this for some special cleanup operation.- Parameters:
ctx
- theChannelHandlerContext
which thisByteToMessageDecoder
belongs toin
- theByteBuf
from which to read data- Throws:
Exception
- is thrown if an error occurs
-