public abstract class ByteToMessageDecoder
extends io.netty.channel.ChannelInboundHandlerAdapter
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())); } }
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.
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.
Modifier | Constructor and Description |
---|---|
protected |
ByteToMessageDecoder()
Create a new instance.
|
Modifier and Type | Method and Description |
---|---|
void |
channelInactive(io.netty.channel.ChannelHandlerContext ctx) |
void |
channelRead(io.netty.channel.ChannelHandlerContext ctx,
java.lang.Object msg) |
void |
channelReadComplete(io.netty.channel.ChannelHandlerContext ctx) |
protected void |
cumulationReset()
Resets cumulation.
|
protected abstract void |
decode(io.netty.channel.ChannelHandlerContext ctx,
io.netty.buffer.ByteBuf in)
Decode the from one
ByteBuf to an other. |
protected void |
decodeLast(io.netty.channel.ChannelHandlerContext ctx,
io.netty.buffer.ByteBuf in)
Is called one last time when the
ChannelHandlerContext goes in-active. |
void |
handlerRemoved(io.netty.channel.ChannelHandlerContext ctx) |
protected void |
handlerRemoved0(io.netty.channel.ChannelHandlerContext ctx)
Gets called after the
ByteToMessageDecoder was removed from the actual context and
it doesn't handle events anymore. |
void |
setDiscardAfterReads(int discardAfterReads)
Set the number of reads after which
ByteBuf.discardSomeReadBytes() are called and so free up memory. |
protected io.netty.buffer.ByteBuf |
swapCumulation(io.netty.buffer.ByteBuf cumulation,
io.netty.buffer.ByteBufAllocator allocator)
Swap the existing
cumulation ByteBuf for a new ByteBuf . |
void |
userEventTriggered(io.netty.channel.ChannelHandlerContext ctx,
java.lang.Object evt) |
channelActive, channelRegistered, channelUnregistered, channelWritabilityChanged, exceptionCaught
ensureNotSharable, handlerAdded, isSharable
public final void setDiscardAfterReads(int discardAfterReads)
ByteBuf.discardSomeReadBytes()
are called and so free up memory.
The default is 16
.
It is assumed this method is only called in the associated Channel
's EventLoop
thread, otherwise
external synchronization must be provided.
discardAfterReads
- The number of calls to ChannelHandlerContext.fireChannelRead(Object)
before
attempting to discard bytes from the buffer cumulator.public final void handlerRemoved(io.netty.channel.ChannelHandlerContext ctx)
handlerRemoved
in interface io.netty.channel.ChannelHandler
handlerRemoved
in class io.netty.channel.ChannelHandlerAdapter
protected void handlerRemoved0(io.netty.channel.ChannelHandlerContext ctx)
ByteToMessageDecoder
was removed from the actual context and
it doesn't handle events anymore.ctx
- the ChannelHandlerContext
which this ByteToMessageDecoder
belongs topublic void channelRead(io.netty.channel.ChannelHandlerContext ctx, java.lang.Object msg)
channelRead
in interface io.netty.channel.ChannelInboundHandler
channelRead
in class io.netty.channel.ChannelInboundHandlerAdapter
public void channelReadComplete(io.netty.channel.ChannelHandlerContext ctx)
channelReadComplete
in interface io.netty.channel.ChannelInboundHandler
channelReadComplete
in class io.netty.channel.ChannelInboundHandlerAdapter
protected io.netty.buffer.ByteBuf swapCumulation(io.netty.buffer.ByteBuf cumulation, io.netty.buffer.ByteBufAllocator allocator)
cumulation
ByteBuf
for a new ByteBuf
. This method is called when a
heuristic determines the amount of unused bytes is sufficiently high that a resize / defragmentation of the
bytes from cumulation
is beneficial.
ByteBuf.discardReadBytes()
is generally avoided in this method because it changes the underlying data
structure. If others have slices of this ByteBuf
their view on the data will become corrupted. This is
commonly a problem when processing data asynchronously to avoid blocking the EventLoop thread.
cumulation
- The ByteBuf
that accumulates across socket read operations.allocator
- Used to allocate a new ByteBuf
if necessary.ByteBuf
that is responsible for accumulated socket reads.protected void cumulationReset()
public void channelInactive(io.netty.channel.ChannelHandlerContext ctx)
channelInactive
in interface io.netty.channel.ChannelInboundHandler
channelInactive
in class io.netty.channel.ChannelInboundHandlerAdapter
public void userEventTriggered(io.netty.channel.ChannelHandlerContext ctx, java.lang.Object evt) throws java.lang.Exception
userEventTriggered
in interface io.netty.channel.ChannelInboundHandler
userEventTriggered
in class io.netty.channel.ChannelInboundHandlerAdapter
java.lang.Exception
protected abstract void decode(io.netty.channel.ChannelHandlerContext ctx, io.netty.buffer.ByteBuf in) throws java.lang.Exception
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
.ctx
- the ChannelHandlerContext
which this ByteToMessageDecoder
belongs toin
- the ByteBuf
from which to read datajava.lang.Exception
- is thrown if an error occursprotected void decodeLast(io.netty.channel.ChannelHandlerContext ctx, io.netty.buffer.ByteBuf in) throws java.lang.Exception
ChannelHandlerContext
goes in-active. Which means the
channelInactive(ChannelHandlerContext)
was triggered.
By default this will just call decode(ChannelHandlerContext, ByteBuf)
but sub-classes may
override this for some special cleanup operation.ctx
- the ChannelHandlerContext
which this ByteToMessageDecoder
belongs toin
- the ByteBuf
from which to read datajava.lang.Exception
- is thrown if an error occurs