Netty Source Learning-delimiterbasedframedecoder

Source: Internet
Author: User

Look at the API of Delimiterbasedframedecoder, there are examples:

The Channelbuffer received are as follows:

+--------------+ | abc\ndef\r\n | +--------------+

After Delimiterbasedframedecoder (Delimiters.linedelimiter ()), get:

+-----+-----+ | ABC | DEF | +-----+-----+

Instead of

+----------+ | Abc\ndef |

Why?

First, be clear, if not specified, delimiterbasedframedecoder default will remove the delimiter

Next look at Delimiters.linedelimiter (), which returns two sets of delimiter, corresponding to windows and Linux line breaks

public static channelbuffer[] Linedelimiter () {        return new channelbuffer[] {                Channelbuffers.wrappedbuffer (new byte[] {' \ r ', ' \ n '},                Channelbuffers.wrappedbuffer (new byte[] {' \ n '}),        };    

Examine the two sets of separators

Programme I

with "\ r \ n" as the separator, the return

Framea = "Abc\ndef"

Programme II

return with "\ n"

Frameb_0 = "ABC"

frameb_1 = "Def\r"

Since the length of the frameb_0 is shorter than the Framea, in this case, Scenario II is used

But there is a question, why not compare all, but only compare frameb_0?

To know, length (FRAMEA) = Length (frameb_0) + length (frameb_1), both equal

At first, I thought, like split, scenario two would return "abcdef\r" one time.

Not actually.

It is encountered with a delimiter and returns a result

This can be demonstrated by the following code:

public class ClientHandler extends Simplechannelupstreamhandler {    @Override public    void channelconnected ( Channelhandlercontext CTX, channelstateevent e)            throws Exception {        String msg = "abc\ndef\r\n";        Channelbuffer buff = Channelbuffers.buffer (Msg.length ());        Buff.writebytes (Msg.getbytes ());        E.getchannel (). write (buff);    }}

Server:

Bootstrap.setpipelinefactory (New Channelpipelinefactory () {public            channelpipeline Getpipeline () throws Exception {                Channelpipeline pipeline = Channels.pipeline ();//Set here: Do not remove delimiters, easy to observe                pipeline.addlast ("Handler1", New Delimiterbasedframedecoder (8192, False, Delimiters.linedelimiter ()));                Pipeline.addlast ("Handler2", New Serverstringhandler ());// print decode result                return pipeline;            }        );

Serverstringhandler:

public class Serverstringhandler extends simplechannelupstreamhandler{    @Override public    void messagereceived (Channelhandlercontext ctx, messageevent e)            Throws Exception {        Channelbuffer buff = (channelbuffer) e.getmessage ();        String msg = (string) buff.tostring (Helper.charset_utf8);                String s = "abc\n"; The Msg_escape will output "abc\n" instead of "abc" plus a newline        String msg_escape = Stringescapeutils.escapejava (msg);          System.out.println ("msg =" + Msg_escape);}    }

Results Serverstringhandler will be output two times:

msg = Abc\nmsg = def\r\n

View the source code, will be more clear:

public class Delimiterbasedframedecoder extends Framedecoder {private final channelbuffer[] delimiters; Private final int maxframelength;/* Returns the result, whether the usual call to remove the delimiter is to remove the delimiter, such as New Delimiterbasedframedecoder (8192, Delimiters.linedelimiter ()) is equivalent to the new Delimiterbasedframedecoder (8192,/*stripdelimiter=*/true, Delimiters.linedelimiter ()) */private Final Boolean stripdelimiter; @Override protected Object decode (Cha Nnelhandlercontext CTX, channel channel, Channelbuffer buffer) throws Exception {//Try all delimiters and choose        The delimiter which yields the shortest frame.        int minframelength = Integer.max_value; Channelbuffer Mindelim = null;/* iteration for each delimiter, try to decode, and then choose the shortest that returns "delimiter frame" in indexof this method */for (            Channelbuffer delim:delimiters) {int framelength = indexOf (buffer, delim);                if (framelength >= 0 && framelength < minframelength) {minframelength = Framelength; MiNdelim = Delim;            }} if (Mindelim! = null) {int mindelimlength = mindelim.capacity ();            Channelbuffer frame;                if (stripdelimiter) {frame = Buffer.readbytes (minframelength);            Buffer.skipbytes (mindelimlength);            } else {frame = Buffer.readbytes (minframelength + mindelimlength);        } return frame; }}/* the frame (haystack) to find the first delimiter (needle), this position is recorded as I return (I-haystack.readerindex), that is, the length of the first sub frame after separation can be seen, it is " Find one and return a "*/private static int indexOf (Channelbuffer haystack, channelbuffer needle) {//Traversal haystack for each byte for (int i = Haystack.readerindex (); I < Haystack.writerindex ();            i + +) {int haystackindex = i; int Needleindex;/*haystack Whether delimiter appears, note delimiter is a channelbuffer (byte[]) For example haystack= "Abc\r\ndef", needle= "\ r\n "Then when haystackindex=3, found" \ r ", at this time needleindex=0 continue to execute the loop, haystackindex++,needleindex++, found" \ n "So far, the entire needle matchThe program then executes to the IF (Needleindex = = Needle.capacity ()) and returns the result */for (Needleindex = 0; Needleindex < needle.capacity ();                    Needleindex + +) {if (Haystack.getbyte (haystackindex)! = Needle.getbyte (Needleindex)) {                Break                    } else {haystackindex + +;                        if (Haystackindex = = Haystack.writerindex () && Needleindex! = needle.capacity ()-1) {                    return-1;  }}} if (Needleindex = = Needle.capacity ()) {//Found the needle from                The haystack!            return I-haystack.readerindex ();    }} return-1; }}

Netty Source Learning-delimiterbasedframedecoder

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.