Implementation of message routing based on NIO (IV.) server-side communication main thread (1)

Source: Internet
Author: User

First, Brief introduction:

The main thread of the server-side communication is the startup class of the message routing service, which has the following functions:

1, the initialization of the relevant configuration;

2, according to the configured IP and port to create TCP services;

3, receives the client connection, and assigns the token to the client;

4, receive the client's login request, and the client-related information (token, client login ID, last access time, the channel used by the current token to save to the buffer)

5, receive the client's message request, and add to the communication queue, waiting for processing;

6, receive instructions from all over the sending request, and send to the relevant channel;

Second, Detailed introduction:

1, start the method: Load configuration information First, and then start the main thread, the communication message consumption thread (processing the communication packet), timeout, failure channel recycling thread (for time-outs and recovery of the failed channel), Short message consumer thread (specifically for the short Message Queue processing thread). In particular, Op_write, after op_write, must be selector registered as Op_read, otherwise it will continue to cycle, die cycle.

Public static void main (string arg[])  throws Exception {     //Initializing configuration Data     config cfg = new config (Arg[0]);     final gvserver gvserver = new gvserver ();     // Start ServerSocket channel     if  (Gvserver.initserver (CFG))  {         executorservice threadpool = executors.newcachedthreadpool ();         //Start the Communication service main thread          Threadpool.execute (gvserver);         //start communication messages consumer thread          threadpool.execute (New cqueueconsumer (Cfg.getwaittime ()));         //start timeout channel, fail channel recycle thread          Threadpool.execute (New conntimeoutcleanthread (cfg.getcLeanthreadouttime (),  cfg.getcleanthreadcycle ());         Threadpool.execute (New mqueueconsumer ());     }}

2, initialization configuration: Open TCP service waiting for connection (slightly);

3, Communication event Processing: The main thread of the communication Run method, mainly connected to receive the event processed separately. This place is especially important to note that, as I mentioned in my first article, all the triggering time must be consumed, otherwise it will continue to circulate.

    public void run ()  {         while  (True)  {            try {                 //Monitoring Event Key                  Selector.select (;              )   //iterating over a set of events key                 iterator<selectionkey> keys = selector.selectedkeys (). Iterator ();                 while  (Keys.hasnext () )  {                     //define a socket channel                      socketchannel socketchannel = null;                     int count = 0;                      Selectionkey key = keys.next ();                     //  logs.info ("A network event is triggered, the event type is:"  +  key.interestops ());                     //Delete the current key in iterator to avoid duplicate processing                      keys.remove ();                     if  (!key.isvalid ())  {                          continue;                     } else if  (Key.isacceptable ())  {                          //get ServerSocket Channel from key sent by client                           serversocketchannel =  (Serversocketchannel)  key.channel ();                         // Receive the socket channel in this ServerSocket channel, accept is a blocking method,Continue until you get to the connection                          socketchannel = serversocketchannel.accept ();                          //set this socket channel to non-blocking mode                           Socketchannel.configureblocking (False);                         //registers this channel with selector and waits for the receiving client's read-in data                          socketchannel.register (Selector, selectionkey.op_read);           &nbSp;             alloctoken (SocketChannel);                      } else if  (Key.isreadable ())  {                         // Get the channel                in event key          socketChannel =  (Socketchannel)   Key.channel ();                         bytebuffer bytebuffer = bytebuffer.allocate ( Config.getreadblock ());                         //Clean buffer for easy use                          bytebuffer.clear ();                          //reads the byte stream in the channel into the buffer                          count = socketchannel.read (ByteBuffer);                          bytebuffer.flip ();                         //Handling Adhesive Bags                           if  (count > 0)  {                             try  {                                 handlepacket ( Socketchannel, bytebuffer);                             } catch  ( Exception e)  {                                  E.printstacktrace ();//                    &nbsp            continue;//if the current package has an illegal throw exception, Then no more processing directly out of the loop, processing the next package; In doubt, the test phase is temporarily annotated                              }                          } else if  (count == 0)  {                              continue;                         } else {                               socketchannel.close ();                             logger.info ("Client" + Socketchannel.tostring () + "Connection off!" ");                         }                     } else if  (Key.iswritable ())  {                           ((Socketchannel)  key.channel ()). Register (SELECTOR,&NBSP;SELECTIONKEY.OP_ READ);                     }                }            } catch  ( Ioexception e)  {                 e.printstacktrace ();             }         }    }

4, the legal message into the communication queue: I in the configuration initialization, the explicit provision of a number of message classes, and in the protocol to define the format of the message, usually not in line with my message format is considered illegal messages, directly to the client to reply to a wrong command.

/** *  handles illegal messages and puts legitimate messages in queue for processing  * *  @param  socketChannel *  @param   Strpacket */private void offerpacket (socketchannel socketchannel, string  Strpacket)  {    ipacket packet = analysetools.analysepacket (StrPacket) ;    if  (Packet.getheader (). Equals (Loginpacket.header))  {         handleloginpacket (Socketchannel, packet);    }     //if the class is empty or cannot be taken from a handle single map, the message is illegal     if  (packet == null  | |  config.getpacketinstance (Packet.getheader ())  == null)  {         //not in the service-side identification of the message, reply to e response, informing the client is not legal         errororder  errorOrder =  (Errororder)  config.getorderinstance (errororder.header);          Errororder.initerrororder (errororder.invaild_req_code, errororder.invaild_req_msg);         logger.info ("Client sends illegal message:"  + strpacket);         gvserver.write2client (Errororder, socketchannel);         //the legitimate message into the message queue for processing     } else {         if  (! GVQueue.CQUEUE.offer (packet))  {             Logger.error ("Message Queuing is full, increase the queue capacity!") ");        } else {             if  (logger.isdebugenabled ())  {                 logger.debug ("will be added to Message Queuing, the number of messages in the queue is:"  +  gvqueue.cqueue.size ());             }        }    }} 

5, assign the client token: After the client connection, the server will immediately reply to the client a T instruction, tell the client its token, from then on, the client each message, must carry this token; In the communication layer, the service side determines the client based on token;

    private void alloctoken (Socketchannel socketchannel)  {   The       //assigns the channel to the connection token         tokenorder tokenorder =  (Tokenorder)  config.getorderinstance (TokenOrder.HEADER);         string token = uuid.randomuuid (). toString ();         tokenorder.inittokenorder (token);         //returned to the client token        write2client (tokenOrder,  Socketchannel);         logger.info ("Client:<"  + token +   "> Already connected! ")         //Save the connected channel to the global map          //2015.8.13 Modify, first save the userid as null, waiting for the user to log in, the,//         Gvconnection gvconnEction = new gvconnection (TOKEN,NULL,&NBSP;SOCKETCHANNEL,&NBSP;COMMONTOOLS.SYSTEMTIMEUTC ());//         gvconntools.addconn2cache (gvconnection);     }

6, Client Login processing: With the client token, I can not use the service for the business, there will always be a user tag in the business, I need to be able to write messages to the channel based on the user's tag, so, with the client logon process, the client submits its own unique business token to the server. The server establishes a token, a user token, a user's last access time, a channel buffer (unified into a class gvconnection), the sending of a special language instruction, and the synchronization of several things, gvconntools the only entry for manipulating these contents;

/** * specializes in handling client login messages, saving gvconn to buffer * "Note" for the UserID duplication situation, here does not do the processing, by the business system itself, * here the UserID repeat equivalent after the login user replaced the first user's channel.    * * @param socketchannel * @param packet */private void Handleloginpacket (Socketchannel socketchannel, IPacket packet) { Gvconnection gvconn = new Gvconnection (Packet.getclienttoken (), Packet.getpacketbody (), Socketchannel, Common    TOOLS.SYSTEMTIMEUTC ()); Gvconntools.addconn2cache (gvconn);}

7, message write channel: In fact, I can provide a special writing method on the outside of Thunder, but it seems that the brain is in the water, and this later iteration is thinking about how to deal with it. Put it here for the time being. It is important to note that this method is the only way to encapsulate the first four bits of the protocol, and in all other classes there is no need to consider the first four bits of the message. When the client reads, the first four bits are also intercepted, or the string is placed in the queue, or a message (instruction) object is placed in the queue. (Why do I need these four bits, I will explain in the next small part-sticky bag, broken package)

/** *  How to write information to clients  * *  @param  iOrder          Message Processing class interface  *  @param  socketchannel */public static synchronized void  write2client (Iorder iorder, socketchannel socketchannel)  {     Try {        socketchannel.register (selector,  Selectionkey.op_write)         //Create a bytebuffer to store the buffer  to write to        bytebuffer bytebuffer = bytebuffer.allocate ( Config.getwriteblock ());         //the length of the entire package          string packetsize = integer.tostring (IOrder.generateOrderStr (). getBytes (). length);         //the top four bits of the package body into buffer          bytebuffer.put (packetsize.getbytes ());         //move buffer's postion pointer to fourth bit, the package will be written from fourth bit to          bytebuffer.position (packet_head_length);         string str = iorder.generateorderstr ();         //Write Package         if  (logger.isdebugenabled ())  {             logger.debug ("Packet of the service-side write channel:" &NBSP;+&NBSP;STR);         }         Bytebuffer.put (Str.getbytes ());         bytebuffer.flip ();         socketchannel.write (Bytebuffer);    } catch  (ioexception e)  {        e.printstacktrace ();     }}

8, sticky bag, broken package.

Halo, the server can not save so much text, I open another chapter, sorry AH.







Implementation of message routing based on NIO (IV.) server-side communication main thread (1)

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.