Protocol codecs are the objects you need to pay attention to when using Mina, because the data transmitted over the network is binary data (bytes ), but you are targeting Java objects in the program, which requires you to encode the binary data of the Java object when sending data, when receiving data, the binary data is decoded as a Java object (note that this is not the serialization or deserialization of Java objects ).
1) encoding: encoding is the process of replacing the attribute content of a common object with the attribute content of a binary object in sequence.
2) decoding: the process of converting a binary object field to a common object attribute field.
1. codec Factory: Provides call portals for coding and decoding implementation
The Protocol decoder in Mina is constructed by the protocolcodecfilter filter. The construction method of this filter requires a protocolcodecfactory,
There are two methods in protocolcodecfactory:
Public interface protocolcodecfactory {protocolencoder getencoder (iosession session) throws exception; // protocolencoder is the interface protocoldecoder getdecoder (iosession session) throws exception to be implemented by the custom encoder; // protocoldecoder is the interface to be implemented by the custom decoder}
Take the message passing factory as an example:
// Codec generation factory public class messageprotocolcodecfactory implements protocolcodecfactory {private protocolencoder encoder; private protocoldecoder decoder; Public messageprotocolcodecfactory () {This (charset. forname ("UTF-8");} public messageprotocolcodecfactory (charset) {encoder = new messageencoder (charset); decoder = new messagedecoder (charset );} @ override public protocoldecoder getdecoder (iosession arg0) throws exception {return decoder;} @ override public protocolencoder getencoder (iosession arg0) throws exception {return encoder ;}}
2. message transmission object: The object that loads the transmitted data
The following is the sample code: (simulate the encoding/Decoding of mobile phone information, message format: Message Header, sender, receiver, content length, content information)
Msgobject. Java: Message entity class
Public class msgobject {// the sender's private string sender; // the receiver's private string Explorer; // The message content is private string content; Public String getsender () {return sender ;} public void setsender (string sender) {This. sender = sender;} Public String getreceiver () {return receiver;} public void setreceiver (string receiver) {This. author ER = author er;} Public String getcontent () {return content;} public void setcontent (string content) {This. content = content ;}}
3. message encoder: messageencoder. Java, which implements protocolencoder or inherits from protocolencoderadapter
// Message encoder public class messageencoder extends protocolencoderadapter {private charset; Public messageencoder (charset) {This. charset = charset ;}@ override public void encode (iosession session, object message, protocolencoderoutput out) throws exception {msgobject MSG = (msgobject) message; // generate character encoder charsetencoder = charset. newencoder (); // get the content of the object property to be sent, ready to encode string status = "m SIP: wap.fetion.com.cn SIP-C/2.0"; string sender = MSG. getsender (); string worker ER = MSG. getcycler (); string content = MSG. getcontent (); // open up a cache space and set it to automatically adjust the iobuffer = iobuffer. allocate (1, 100); iobuffer. setautoexpand (true); // put the information to be sent into the cache space // iobuffer of the message header. putstring (status + "\ n", charsetencoder); // message sender iobuffer. putstring ("s:" + sender + "\ n", charsetencoder); // Message Receiver iobuffer. putstring ("R:" + receiver + "\ n", charsetencoder); // The iobuffer of the message content. putstring ("L:" + content. getbytes (charset ). length + "\ n", charsetencoder); // iobuffer of message content. putstring (content + "\ n", charsetencoder); // The encoded information is included in iobuffer and written back to iobuffer. flip (); out. write (iobuffer );}}
4. message decoder: messagedecoder. Java, which implements protocoldecoder or inherits from protocoldecoderadapter
// Message decoder public class messagedecoder extends protocoldecoderadapter {private charset; Public messagedecoder (charset) {This. charset = charset ;}@ override protected Boolean dodecode (iosession session, iobuffer in, protocoldecoderoutput out) throws exception {charsetdecoder chardecoder = charset. newdecoder (); iobuffer buffer = iobuffer. allocate (100 ). setautoexpand (true); // receives the decoded message string status = ""; string sender = ""; string explorer = ""; string contentlen = ""; string content = ""; int textlinenumber = 1; int columnnumber = 0; // if there is a message in the cache while (in. hasremaining () {byte bt = in. get (); buffer. put (BT); // line feed if (bt = 10 & textlinenumber <5) {columnnumber ++; If (textlinenumber = 1) {buffer. flip (); status = buffer. getstring (columnnumber, chardecoder); status = status. substring (0, status. length ()-1); columnnumber = 0; buffer. clear ();} If (textlinenumber = 2) {buffer. flip (); Sender = buffer. getstring (columnnumber, chardecoder); Sender = sender. substring (0, sender. length ()-1); columnnumber = 0; buffer. clear ();} If (textlinenumber = 3) {buffer. flip (); runner ER = buffer. getstring (columnnumber, chardecoder); Cycler = cycler. substring (0, author er. length ()-1); columnnumber = 0; buffer. clear ();} If (textlinenumber = 4) {buffer. flip (); contentlen = buffer. getstring (columnnumber, chardecoder); contentlen = contentlen. substring (0, contentlen. length ()-1); columnnumber = 0; buffer. clear () ;}textlinenumber ++;} else if (textlinenumber = 5) {columnnumber ++; If (columnnumber = long. parselong (contentlen. split (":") [1]) {buffer. flip (); content = buffer. getstring (columnnumber, chardecoder); textlinenumber ++; break ;}} else {columnnumber ++ ;}} msgobject smsobject = new msgobject (); smsobject. setsender (sender. split (":") [1]); smsobject. setaggreger (aggreger. split (":") [1]); smsobject. setcontent (content); out. write (smsobject); Return false ;}}
5. Some things to know about the Mina Codec
1) it is best to understand the read operations of Mina iobuffer.
2) call these codecs in the filter for object transmission and write the master programs on the server and client.
3) Check whether object decoding is performed in batches.
The above message decoder (messagedecoder. in Java), the message is sent from the server at a time, but sometimes the message may not be sent from the server at a time, but is divided into several batches, in this case, the decode () method of the decoder is repeatedly called. The state variables textlinenumber and columnnumber are reset, so the state variables must be saved. You may think of saving the state variables in the decoder's member variables, but Mina does not guarantee that every call to the decode () method is the same thread, so the state variables are not thread-safe. Therefore, you need to save the state variables to the iosession because the iosession uses a synchronized hashmap to save the object (the Session Initiated by the client and the server is not the same process, so the session is not the same session, mina is an event-driven asynchronous API ).
Save the status variable in iosession:
// Key value of the object storing data status private final attributekey context = new attributekey (getclass (), "context"); // use iosession. setattribute and iosession. the object private msgcontext getcontext (iosession session) {msgcontext context = (msgcontext) session. getattribute (context); If (null = context) {context = new msgcontext (); Session. setattribute (context, context);} return context ;}