Netty series six (codec).

Source: Internet
Author: User
Tags readable
First, the concept

The unit of the network transmission is bytes, how to convert the application's data to bytes, and the conversion of bytes to the data of the application, it is necessary to mention the encoder and decoder we introduced in this article.

The components that convert the application's data to a network format and the data that transforms the network format into an application are called encoders and decoders, and a single component with both features is called a codec. Netty provides a range of tools for creating all of these encoders, decoders, and codecs, as well as customizing the generic message conversion codec on demand.

Netty (solution) code implements the Channelhandleradapter, is also a special channelhandler, so depending on the channelpipeline, can be a number of coding (solution) code to link together to achieve complex conversion logic.

For encoders and decoders, the process is fairly straightforward: once the message is encoded or decoded, it is automatically freed by the Referencecountutil.release (message) call. If you need to keep the reference for later use, you can call the Referencecountutil.retain (message) method. This will increase the reference count to prevent the message from being freed.

Second, encoder

The encoder converts the application's data into a network format, which is called when the outbound message is in two main categories:

1. Encode the message into bytes: Messagetobyteencoder
 public  abstract  class  messagetobyteencoder<i> extends  channelhandleradapter{} 
 Public class extends Messagetobyteencoder<short> {        /**     * 1, the outbound message of type I is encoded as Bytebuf     * 2, the BYTEBUF It will then be forwarded to the next Channeloutboundhandler in Channelpipeline.      */     @Override    protectedvoidthrows  Exception {        Bytebuf.writeshort (Ashort);    }}
2. Encode the message as a message: Messagetomessageencoder
 public  abstract  class  messagetomessageencoder<i> extends  Channelhandleradapter {}
 Public class extends Messagetomessageencoder<integer> {        /**     * 1, the outbound message of type I is encoded as the target type in list     * 2, the The list will then be forwarded to the next Channeloutboundhandler in the Channelpipeline.      */     @Override    protectedvoidthrows  Exception {        Out.add (string.valueof (msg));}    }
Third, decoder

The decoder converts the network format to the application's data, which is called when the inbound message is entered.

The decoder has a more decodelast method than the encoder because the decoder usually needs to produce the last message after the Channel is closed. This obviously does not apply to the encoder scene-it is meaningless to still produce a message after the connection is closed. Therefore, this method will be called once when the Channel's state becomes inactive. You can override this method to provide special handling.

There are two main types of decoders:

1. Decoding bytes to messages: Bytetomessagedecoder and Replayingdecoder
 Public Abstract class extends Channelhandleradapter {}
 Public classMydecoderextendsBytetomessagedecoder {Private Static Final intMax_frame_size = 1024; /*** 1, when the method is called, it will pass in a bytebuf containing the incoming data, and a List to add the decoded message.     * 2, the call to the method will be repeated until it is determined that no new element is added to the List, or butebuf no more readable bytes.     * 3, the contents of the List will be passed to the next channelinboundhandler in Channelpipeline. */@Overrideprotected voidDecode (Channelhandlercontext Channelhandlercontext, Bytebuf bytebuf, list<object> List)throwsException {intReadablebytes =bytebuf.readablebytes (); //cannot allow the decoder to buffer large amounts of data so that the available memory is exhausted        if(Readablebytes >max_frame_size) {            //Skip all the readable bytesbytebuf.skipbytes (readablebytes); Throw NewToolongframeexception ("Data is more than cacheable bytes ..."); }        //Suppose you need to parse a message of type int (int 4 bytes)        if(Readablebytes > 4) {List.add (Bytebuf.readint ()); }    }}

----Split Line----

// The type parameter S specifies the type to use for state management, where Void represents no need for state management.  Publicabstractclassextends bytetomessagedecoder{}
 Public classMyreplayingdecoderextendsReplayingdecoder<void> {    /*** 1, Replayingdecoder expands the Bytetomessagedecoder, and customizes the implementation replayingdecoderbytebuf of BYTEBUF.     * 2. REPLAYINGDECODERBYTEBUF internal management of the number of bytes of messages to be converted, and if not enough bytes are used, a Signal will be thrown and processed by Replayingdecoder. *     * @parambytebuf incoming bytebuf is actually replayingdecoderbytebuf.*/@Overrideprotected voidDecode (Channelhandlercontext Channelhandlercontext, Bytebuf bytebuf, list<object> List)throwsException {list.add (Bytebuf.readint ()); }}

What is the difference between inheriting Bytetomessagedecoder and inheriting Replayingdecoder? The only benefit of replayingdecoder is that it does not have to be a byte-count when decoding, as it is handled by a custom replayingdecoderbytebuf. But Replayingdecoder's efficiency is slightly slower than bytetomessagedecoder. In general, our choice between the two decoders is that if using bytetomessagedecoder does not introduce too much complexity, use it; otherwise, use the replayingdecoder!

2. Decode the message as a message: Messagetomessagedecoder
 Public Abstract class extends channelhandleradapter{}
 Public class extends Messagetomessageencoder<integer> {        /**     * 1, this method will be called for each inbound message that needs to be decoded to another format.     * 2. The decoded message is then passed to the next Channelinboundhandler     in Channelpipeline */     @Override    protectedvoidthrows  Exception {        List.add (string.valueof (integer));}    }
Four, codec

Netty's abstract codec class bundles a decoder/encoder pair, which is primarily used to manage the conversion of inbound and outbound data and messages in the same class.

Personally think this codec is slightly chicken, or like to separate encoder and decoder to write. Because one of the basic principles of Netty design is to separate the two functions (encoders, decoders) as much as possible to maximize the reusability and extensibility of the code.

There are two main types of codecs:

1, byte message codec: Bytetomessagecodec
 Public Abstract class extends Channelhandleradapter {}
 Public class extends Bytetomessagecodec<short> {        @Override    protectedvoidthrows  Exception {        while (In.readablebytes () > 4) {            out.add (In.readint ());        }    }    @Override    protectedvoidthrows  Exception {        Out.writeshort ( msg);}    }
2. Message Conversion Codec: MESSAGETOMESSAGECODEC
 Public Abstract class extends Channelhandleradapter {}
 Public classWebsocketconverthandlerextendsMessagetomessagecodec<websocketframe, websocketconverthandler.mywebsocketframe> {    /*** 1, for each outbound_in type of message, this method will be called.     * 2, this message will be encoded as a inbound_in type of message. * 3, then forwarded to the next Channeloutboundhandler in Channelpipeline*/@Overrideprotected voidEncode (Channelhandlercontext ctx, Mywebsocketframe msg, list<object> out)throwsException {bytebuf bytebuf=msg.getbytebuf (). Duplicate (). retain (); Switch(Msg.getframetype ()) { CaseBINARY:out.add (NewBinarywebsocketframe (BYTEBUF));  Break;  CaseTEXT:out.add (NewTextwebsocketframe (BYTEBUF));  Break;  CaseCLOSE:out.add (NewClosewebsocketframe (true, 0, Bytebuf));  Break;  CaseCONTINUATION:out.add (NewContinuationwebsocketframe (BYTEBUF));  Break;  CasePONG:out.add (NewPongwebsocketframe (BYTEBUF));  Break;  CasePING:out.add (NewPingwebsocketframe (BYTEBUF)); default:                 Break; }    }    /*** 1, incoming inbound_in type of message, the method will be called.     * 2, this message will be decoded to the outbound_in type of message. * 3, then forwarded to the next Channelinboundhandler in Channelpipeline*/@Overrideprotected voidDecode (Channelhandlercontext ctx, Websocketframe msg, list<object> out)throwsException {bytebuf bytebuf=msg.content (). Duplicate (). retain (); if(msginstanceofbinarywebsocketframe) {Out.add (Newmywebsocketframe (MyWebSocketFrame.FrameType.BINARY, bytebuf)); } Else if(msginstanceofclosewebsocketframe) {Out.add (Newmywebsocketframe (MyWebSocketFrame.FrameType.CLOSE, bytebuf)); } Else if(msginstanceoftextwebsocketframe) {Out.add (Newmywebsocketframe (MyWebSocketFrame.FrameType.TEXT, bytebuf)); } Else if(msginstanceofpingwebsocketframe) {Out.add (Newmywebsocketframe (MyWebSocketFrame.FrameType.PING, bytebuf)); } Else if(msginstanceofpongwebsocketframe) {Out.add (Newmywebsocketframe (MyWebSocketFrame.FrameType.PONG, bytebuf)); } Else if(msginstanceofcontinuationwebsocketframe) {Out.add (Newmywebsocketframe (MyWebSocketFrame.FrameType.CONTINUATION, bytebuf)); } Else {            Throw NewIllegalStateException ("Unsupported websocket msg" +msg); }    }     Public Static Final classMywebsocketframe { Public enumFrametype {BINARY, CLOSE, PING, PONG, TEXT, CONTIN Uation}Private FinalFrametype Frametype; Private FinalBytebuf Bytebuf;  PublicMywebsocketframe (Frametype frametype, Bytebuf bytebuf) { This. Frametype =Frametype;  This. Bytebuf =Bytebuf; }         PublicFrametype GetFrameType () {returnFrametype; }         Publicbytebuf getbytebuf () {returnBytebuf; }    }}
This kind of writing is still very good ~ ~

reference:"Netty in ACTION"

Demo Source code:

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.