This is the 17th day of my participation in the August More text Challenge. For details, see:August is more challenging

Introduction to the

In the last article, we talked about how to customize the code and decoder in Netty, but it is quite complicated to implement the custom. In general, there is no special need, and everyone wants to be as simple as possible. The difficulty is to find the segmentation point in The ByteBuf, and divide the ByteBuf into a single unit that can be handled. In today’s article, we talk about the segmentation mechanism that comes with Netty.

Frame detection

In the previous chapter, we mentioned the need for a means to distinguish the different data in ByteBuf, that is, to find the split point of different data in ByteBuf. It is much easier to deal with the individual ByteBuf if you first split it into individual bytebufs.

Netty provides an encoder with four split points, which we can call Frame detection, They are respectively DelimiterBasedFrameDecoder FixedLengthFrameDecoder LengthFieldBasedFrameDecoder, and LineBasedFrameDecoder.

These classes are subclasses of ByteToMessageDecoder, and we will introduce them one by one.

DelimiterBasedFrameDecoder

First is DelimiterBasedFrameDecoder, see how the name for this is based on a delimiter bytebuf segmentation of decoder. What is Delimiter?

Netty has a Delimiters class that defines Delimiters. There are mainly two Delimiters, nulDelimiter and lineDelimiter:

public static ByteBuf[] nulDelimiter() {
        return new ByteBuf[] {
                Unpooled.wrappedBuffer(new byte[] { 0 }) };
    }

    public static ByteBuf[] lineDelimiter() {
        return new ByteBuf[] {
                Unpooled.wrappedBuffer(new byte[] { '\r', '\n' }),
                Unpooled.wrappedBuffer(new byte[] { '\n' }),
        };
    }
Copy the code

NullDelimiter handles 0x00, mainly for Flash XML sockets or other similar protocols.

LineDelimiter is used to handle carriage returns and newlines, and is mainly used in text file processing.

For DelimiterBasedFrameDecoder, if there are multiple delimiter, will choose the shortest split ByteBuf that, for example, If we use DelimiterBasedFrameDecoder (Delimiters. LineDelimiter ()), because there are actually two segmentation of lineDelimiter way, + line breaks or newline, if you meet the following conditions:

   +--------------+
   | ABC\nDEF\r\n |
   +--------------+
Copy the code

DelimiterBasedFrameDecoder will choose the shortest segmentation result, also said to be split the contents of the above:

   +-----+-----+
   | ABC | DEF |
   +-----+-----+
Copy the code

Rather than

   +----------+
   | ABC\nDEF |
   +----------+
Copy the code

FixedLengthFrameDecoder

This class will divide ByteBuf into fixed lengths, such as the following four byte messages received:

   +---+----+------+----+
   | A | BC | DEFG | HI |
   +---+----+------+----+
Copy the code

If a FixedLengthFrameDecoder(3) is used, the above ByteBuf is divided into the following sections:

   +-----+-----+-----+
   | ABC | DEF | GHI |
   +-----+-----+-----+
Copy the code

LengthFieldBasedFrameDecoder

This class is a little more flexible and can extract subsequent byte arrays based on the length field in the data. LengthFieldBasedFrameDecoder is very flexible, it has four properties to control their lengthFieldOffset, lengthFieldLength, lengthAdjustment and initialBytesToStrip.

LengthFieldOffset is the start position of the length field, lengthFieldLength is the length of the length field itself, and lengthAdjustment is to adjust the length of the target data. Initialbyteststrip is the number of bytes to be deleted during decryption. Don’t get it? That’s all right. Let’s do some examples.

Let’s start with the simplest one:

   lengthFieldOffset   = 0
   lengthFieldLength   = 2
   lengthAdjustment    = 0
   initialBytesToStrip = 0 

   BEFORE DECODE (14 bytes)         AFTER DECODE (14 bytes)
   +--------+----------------+      +--------+----------------+
   | Length | Actual Content |----->| Length | Actual Content |
   | 0x000C | "HELLO, WORLD" |      | 0x000C | "HELLO, WORLD" |
   +--------+----------------+      +--------+----------------+
Copy the code

The above setting indicates that length starts at bit 0 and is 2 bytes long. Ox00C is 12, which is the length of “HELLO, WORLD.”

If you do not want Length, you can delete Length by setting InitialbytestStrip:

LengthFieldOffset = 0 lengthFieldLength = 2 lengthAdjustment = 0 Initialbytest2 = 2 (14 bytes) AFTER DECODE (12 bytes) +--------+----------------+ +----------------+ | Length | Actual Content |----->| Actual Content | | 0x000C | "HELLO, WORLD" | | "HELLO, WORLD" | +--------+----------------+ +----------------+Copy the code

LengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment: lengthAdjustment The real Length is 0x0C, but 0x0E is passed in, so subtract the Length 2 from the Length field and set lengthAdjustment to -2.

LengthFieldOffset = 0 lengthFieldLength = 2 lengthAdjustment = -2 Initialbytest2 = 0 BEFORE DECODE (14 bytes) AFTER DECODE (14 bytes) +--------+----------------+ +--------+----------------+ | Length | Actual Content |----->| Length | Actual Content | | 0x000E | "HELLO, WORLD" | | 0x000E | "HELLO, WORLD" | +--------+----------------+ +--------+----------------+Copy the code

LineBasedFrameDecoder

LineBasedFrameDecoder specializes in handling the end of a line in a text file. That is “\ n” and “\ r \ n”, he and DelimiterBasedFrameDecoder are very similar, but DelimiterBasedFrameDecoder is more general.

conclusion

With the above four Frame detection devices, you can add the Frame detection in the pipline first, and then add the custom handler, so that the custom handler does not have to consider the length of the read ByteBuf.

For example, in a StringDecoder, if the LineBasedFrameDecoder is already used, then the decode method can assume that the ByteBuf passed in is a string.

    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        out.add(msg.toString(charset));
    }
Copy the code

Is it simple?

This article is available at www.flydean.com/15-netty-bu…

The most popular interpretation, the most profound dry goods, the most concise tutorial, many you do not know the small skills waiting for you to find!

Welcome to follow my public number: “procedures those things”, understand technology, more understand you!