Apache Mina Primer (v)--broken package, sticky pack problem solving

Source: Internet
Author: User
Tags object serialization pack

Get started with the previous article Apache Mina (a)-basic knowledge, we can know: Apache Mina Server is a network communication application framework, that is, it is mainly based on TCP/IP, UDP/IP protocol stack Communication Framework (of course, can also provide Java Object serialization service, virtual machine pipeline Communication Service, etc.), Mina can help us quickly develop high-performance, high-scalability network communication applications, Mina provides event-driven, asynchronous (Mina asynchronous IO defaults to using Java NIO as the underlying support) of the programming model.
Getting Started with Apache Mina (ii)--Asynchronous communication mechanism
Apache Mina Getting Started (iii)--Client synchronous communication
Apache Mina Getting Started (four)------Client long connection method to realize disconnection and reconnection monitoring
We can skillfully deal with the problems in the program, but Mina actually has a serious problem, that is, the problem of packet failure--custom or default decoder each read buffered data is limited, that is, the size of the readbuffersize, the default is 2048 bytes, When the packet is larger, it is divided into multiple reads, causing the packet to break. Although we have a rough solution, it is through Acceptor.getsessionconfig (). Setreadbuffersize (newsize) This way to increase the default capacity "The result is that data processing efficiency slows down"

In Mina, the general application scenario with Textline decode and encode is sufficient (textline default delimiter although is \ r \ n, but in fact, the separator can be specified, such as: Newtextlinedecoder (CharSet, Decodingdelimiter);)
Therefore, when the size of the data we receive is not very fixed, and easy to large, the default textline is not appropriate. At this point we need to determine whether the packet is complete before parsing, which can be very cumbersome to handle. Well, fortunately for Mina, Cumulativeprotocoldecoder
Class, from the name of the cumulative protocol decoder, that is, as long as there is data sent, the class will read the data, and then accumulate into the internal iobuffer buffer, but the specific unpacking (the data accumulated to the buffer into a Java object) to the sub-class of Dodecode () Method is done, in fact Cumulativeprotocoldecoder is the Dodecode () method that repeatedly calls the decode () method to the subclass implementation.
The specific execution process is as follows:
A. When your Dodecode () method returns True, the Cumulativeprotocoldecoder decode () method first determines whether you read the data from the internal Iobuffer buffer in the Dodecode () method " The source code is based on the current data read position compared to the previous position, if equal, the data is not read from the cache, conversely, the data has been read from the buffer ", if not, will throw an illegal state exception" throw New IllegalStateException (" Dodecode () can ' t return True when buffer was not consumed. "); ", that is, your Dodecode () method returns True to indicate that the data for the internal iobuffer buffer has been consumed. If the validation passes, then Cumulativeprotocoldecoder checks if there is any data in the buffer that is not read, and if any, continues calling the Dodecode () method "Continue reading from the current read location" without stopping the call to the Dodecode () method.
B. When your Dodecode () method returns false, Cumulativeprotocoldecoder stops the call to the Dodecode () method, but at this point, if the data still has not been read, it will contain the remaining data Iobuffer The buffer is saved to iosession so that the next time the data arrives you can extract the merge from the iosession. If you find that this data is all read, empty the iobuffer buffer.
In short, when you think that the data read is enough to decode, then the part of the data is decoded first, and then the cache to determine whether there is still data, if any, return true, or return false. The most important job of this cumulativeprotocoldecoder is to help you complete the data accumulation, because this job is very cumbersome.

The main code is the decoder:

/** * Decoder * inherits the Cumulativeprotocoldecoder class, realizes to the Mina to break the packet, the sticky packet problem solves * Main idea: * 1, determines whether the current cache goes in the existence data, if exists, then carries on the subsequent processing. * 2, to obtain the message data "message specification: Length (2 bytes) + method Number (1 bytes) + content", first get the length, determine whether the buffer remaining data length and message length is equal, if not equal, representing the message data is incomplete, * return false, need to read from the cache * 3 , equal, then get the method number, content, get to the content, then the part of the complete data to handler processing, * 4, determine if the buffer is still there data, if present, on behalf of the message is also sticky packet.
 Returns True. * @author LIUC * @date 2017-12-22 * */public class Bytearraydecoder extends Cumulativeprotocoldecoder {private S
    Tatic final Logger Logger = Logger.getlogger (Nsprotocaldecoder.class);

    Private final Charset Charset = Charset.forname ("GBK");

    Maximum length of the request message 100k private int maxpacklength = 102400;
    public int getmaxpacklength () {return maxpacklength; } public void Setmaxpacklength (int maxpacklength) {if (maxpacklength <= 0) {throw new Illega
        Largumentexception ("Maximum request message length:" + maxpacklength);
    } this.maxpacklength = Maxpacklength; } @Override protected Boolean Dodecode (iosession session, Iobuffer in, protocoldecoderoutput out) throws Exception {//1, first determine if the data exists if (in.remaining ()
            > 0) {in.mark ();
            1. Get length byte[] sizebytes = new byte[2];
            In.get (sizebytes,0,2);//read 2 bytes byte[] Length_byte_arr = new byte[]{0,0,0,0};
            LENGTH_BYTE_ARR[2] = sizebytes[0];
            LENGTH_BYTE_ARR[3] = sizebytes[1];
            Gets the length of int length = Bytetools.bytearraytoint (Length_byte_arr);
                Length-2 is reduced by 2 because it reads two bytes of length if (in.remaining () < length-2) {in.reset ();
            Represents incomplete message, need to read the buffer again data return false;
            }//Get method number byte[] Funcidbytes = {in.get ()};
            byte[] Funcid_byte_arr = new byte[]{0,0,0,0};
            FUNCID_BYTE_ARR[3] = funcidbytes[0];
            Gets the length int funcid = Bytetools.bytearraytoint (Funcid_byte_arr); System.out.println ("3================================== "+in.remaining ());
            Get content//Read message body contents int oldlimit = In.limit ();
            Logger.debug ("Limit:" + (in.position () + length));
            Current read position + total length-length of bytes read in front in.limit (in.position () + length-3);
            String content = in.getstring (Charset.newdecoder ());
            In.limit (Oldlimit);

            Logger.debug ("Message body content:" + content);
            Basemessageforclient message = new Basemessageforclient ();
            Message.setlength (length);
            Message.setfuncid (FUNCID);
            Message.setcontent (content);
            Out.write (message); Represents a subsequent package that can be re-read, but the previous package has been sent to handler for processing//The problem is known as sticky Packet if (in.remaining () > 0) {RE
            Turn true;
    }} return false; }

}

The encoder code is as follows:

public class Bytearrayencoder extends Protocolencoderadapter {public

    void encode (iosession session, Object message,
            protocolencoderoutput out) throws Exception {
        //TODO auto-generated method stub
        Basemessageforserver Basemessage = (basemessageforserver) message;

        Iobuffer buffer = iobuffer.allocate (n);
        Buffer.setautoexpand (true);

        Buffer.put (Bytetools.inttobytearray (Basemessage.getlength () +3, 2));//Kanenaga
        buffer.put (bytetools.inttobytearray (Basemessage.getfuncid (), 1)); /method Number
        Buffer.put (Basemessage.getcontent (). GetBytes ());//Content
        Buffer.flip ();

        Out.write (buffer);
        Out.flush ();

        Buffer.free ();

    }

}

Source code Download Address: http://download.csdn.net/download/u012151597/10168974

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.