Class ByteToMessageDecoder

  • All Implemented Interfaces:
    io.netty.channel.ChannelHandler, io.netty.channel.ChannelInboundHandler
    Direct Known Subclasses:
    DelimiterBasedFrameDecoder, FixedLengthFrameDecoder, JsonObjectDecoder, LengthFieldBasedFrameDecoder, LineBasedFrameDecoder, ReplayingDecoder

    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 extends ByteToMessageDecoder {
             @Override
             public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
                     throws Exception {
                 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 {@link @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.

    • Field Detail

      • MERGE_CUMULATOR

        public static final ByteToMessageDecoder.Cumulator MERGE_CUMULATOR
        Cumulate ByteBufs by merge them into one ByteBuf's, using memory copies.
      • COMPOSITE_CUMULATOR

        public static final ByteToMessageDecoder.Cumulator COMPOSITE_CUMULATOR
        Cumulate ByteBufs by add them to a CompositeByteBuf and so do no memory copy whenever possible. Be aware that CompositeByteBuf use a more complex indexing implementation so depending on your use-case and the decoder implementation this may be slower than just use the MERGE_CUMULATOR.
    • Constructor Detail

      • ByteToMessageDecoder

        protected ByteToMessageDecoder()
    • Method Detail

      • setSingleDecode

        public void setSingleDecode​(boolean singleDecode)
        If set then only one message is decoded on each channelRead(ChannelHandlerContext, Object) call. This may be useful if you need to do some protocol upgrade and want to make sure nothing is mixed up. Default is false as this has performance impacts.
      • setDiscardAfterReads

        public void setDiscardAfterReads​(int discardAfterReads)
        Set the number of reads after which ByteBuf.discardSomeReadBytes() are called and so free up memory. The default is 16.
      • actualReadableBytes

        protected int actualReadableBytes()
        Returns the actual number of readable bytes in the internal cumulative buffer of this decoder. You usually do not need to rely on this value to write a decoder. Use it only when you must use it at your own risk. This method is a shortcut to internalBuffer().readableBytes().
      • internalBuffer

        protected io.netty.buffer.ByteBuf internalBuffer()
        Returns the internal cumulative buffer of this decoder. You usually do not need to access the internal buffer directly to write a decoder. Use it only when you must use it at your own risk.
      • handlerRemoved

        public final void handlerRemoved​(io.netty.channel.ChannelHandlerContext ctx)
                                  throws Exception
        Specified by:
        handlerRemoved in interface io.netty.channel.ChannelHandler
        Overrides:
        handlerRemoved in class io.netty.channel.ChannelHandlerAdapter
        Throws:
        Exception
      • handlerRemoved0

        protected void handlerRemoved0​(io.netty.channel.ChannelHandlerContext ctx)
                                throws Exception
        Gets called after the ByteToMessageDecoder was removed from the actual context and it doesn't handle events anymore.
        Throws:
        Exception
      • channelRead

        public void channelRead​(io.netty.channel.ChannelHandlerContext ctx,
                                Object msg)
                         throws Exception
        Specified by:
        channelRead in interface io.netty.channel.ChannelInboundHandler
        Overrides:
        channelRead in class io.netty.channel.ChannelInboundHandlerAdapter
        Throws:
        Exception
      • channelReadComplete

        public void channelReadComplete​(io.netty.channel.ChannelHandlerContext ctx)
                                 throws Exception
        Specified by:
        channelReadComplete in interface io.netty.channel.ChannelInboundHandler
        Overrides:
        channelReadComplete in class io.netty.channel.ChannelInboundHandlerAdapter
        Throws:
        Exception
      • discardSomeReadBytes

        protected final void discardSomeReadBytes()
      • channelInactive

        public void channelInactive​(io.netty.channel.ChannelHandlerContext ctx)
                             throws Exception
        Specified by:
        channelInactive in interface io.netty.channel.ChannelInboundHandler
        Overrides:
        channelInactive in class io.netty.channel.ChannelInboundHandlerAdapter
        Throws:
        Exception
      • userEventTriggered

        public void userEventTriggered​(io.netty.channel.ChannelHandlerContext ctx,
                                       Object evt)
                                throws Exception
        Specified by:
        userEventTriggered in interface io.netty.channel.ChannelInboundHandler
        Overrides:
        userEventTriggered in class io.netty.channel.ChannelInboundHandlerAdapter
        Throws:
        Exception
      • callDecode

        protected void callDecode​(io.netty.channel.ChannelHandlerContext ctx,
                                  io.netty.buffer.ByteBuf in,
                                  List<Object> out)
        Called once data should be decoded from the given ByteBuf. This method will call decode(ChannelHandlerContext, ByteBuf, List) as long as decoding should take place.
        Parameters:
        ctx - the ChannelHandlerContext which this ByteToMessageDecoder belongs to
        in - the ByteBuf from which to read data
        out - the List to which decoded messages should be added
      • decode

        protected abstract void decode​(io.netty.channel.ChannelHandlerContext ctx,
                                       io.netty.buffer.ByteBuf in,
                                       List<Object> out)
                                throws Exception
        Decode the from one 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.
        Parameters:
        ctx - the ChannelHandlerContext which this ByteToMessageDecoder belongs to
        in - the ByteBuf from which to read data
        out - the List to which decoded messages should be added
        Throws:
        Exception - is thrown if an error occurs