When speaking the listener said the new socket to be processed to return as soon as possible, the listener is called Clientfactory Createphysicalconnection method, then see this method:
Public Booleancreatephysicalconnection (pushclientsocket socket,BooleanIsobserver, Listeneroptions listeneroptions) {Physicalconnectionpool Thephysicalconnectionpool=Serverimpl.getphysicalconnectionpool (); Ioqueue<PhysicalConnection> Ioqueue =Serverimpl.getioqueue (); //a Physicalconnection object pool is built in, which avoids every time you want to//Create Physicalconnection objects to speed up processingPhysicalconnection connection =Thephysicalconnectionpool.borrowobject (); //associating the Physicalconnection object with the socket objectconnection.reset (socket, isobserver, listeneroptions); //Initialize the protocol, allocate buffer, to cache the data when parsing the request if(!connection.setupprotocolcontexts ()) {Thephysicalconnectionpool.returnobject (connection); return false; } debug.debug ("Physical Connection Created for the client from:" +Socket.getip ()); //register the connection in the I/O queue so that the request can be monitored if(!Ioqueue.addsocketcontext (socket, connection)) {Thephysicalconnectionpool.returnobject (connection); //leave socket close to acceptor return false; } debug.debug ("Queue adds client from:" +Socket.getip ()); //Add the created Physicalconnection to the pending queue, at which point the connection//Is not really connected, wait until the first request arrives and correctly//is not connected until it is processed, and a logicalconnection is created//associated with this physicalconnection .addphysicalconnection (connection); //Initialize PhysicalconnectionServerimpl.getdispatcher (). Handleinitialize (connection); return true; }
Clientfactory is the physicalconnection Management Program, the role of this method is to create physicalconnection and a new socket associated, and the Physicalconnection joins the I/O queue that the request listens to. So, say ioqueue.
The ioqueue itself is an interface:
Public InterfaceIoqueue<t> { Public BooleanCreate (); Public voidFree (); //gets the event from the queue, the default implementation is with a blocking timeout, that is, when there is no event//is blocked for a period of time, and the timeout returns null PublicIoevent<t> Getqueuedevent (Booleanisinputevents); //register a connection, context is an association object, similar to an attachment Public BooleanAddsocketcontext (pushclientsocket socket, T context); //Cancel Registration Public voidDeletesocketcontext (pushclientsocket socket); //Ioqueue Event Monitoring is one-time, this is to prevent the event from being processed before the event//Is captured again (this is the case with Java's Read/write event), so this method//after being processed, the call is registered again. Public BooleanRearmsocketforwrite (pushclientsocket socket, T context); //The Read event represents the data coming from the client . Public BooleanRearmsocketforread (pushclientsocket socket, T context);}
Ioqueueimpl is the implementation of the Java NIO version of Ioqueue. The Ioqueueimpl will have a separate thread and a selector, and there's a little bit to note about registration here:
The Pushclientsocketimpl Registerselector method is used to register the socket, where the wakeup method needs to be called. Because if the standalone thread calls selector's Select method to wait for new data, this time directly
Calling the register method is blocked, so you need to call wakeup wake-up selector first.
Public int Ops, throws IOException { // to prevent block when calling register method return c12> Channel.register (selector, OPS, attachment); }
Then say the independent thread listens to the event, because Op_write's particularity, here only listens to the Op_read event.
Private voidPollevents (Booleanisoutpoll) {Selector Selector; Blockingqueue<SelectionKey>queue; if(isoutpoll) {return; } Else{Selector= This. Inpollselector; Queue= This. Inpollqueue; } List<SelectionKey> cache =NewLinkedlist<selectionkey>(); while(ispolling) {Try{selector.select (); } Catch(IOException e) {Continue; } //here call yield release control is for the Register method just mentioned can be executed smoothlyThread.yield (); //add into cache (add to the blocking queue directly//May block so, the selector cannot release the selection//key in time) if(Selector.isopen ()) { for(Selectionkey Key:selector.selectedKeys ()) {//the Listener event mentioned earlier is a one-time, so the listener is canceled here//later call the Rearm method to re-registerKey.cancel (); Cache.Add (key); } //Clear the keysSelector.selectedkeys (). Clear (); //because a blockingqueue with a limited length is used, it may be blocked because the queue is full//so first move the event into the cache and release the selectorQueue.addall (cache); Cache.clear (); } Else { Break;//Selector closed } } }
By the way, Demultiplexor gets the Getqueuedevent method of the event call, which uses blockingqueue to implement blocking waits:
PublicIoevent<physicalconnection> Getqueuedevent (Booleanisinputevents) { FinalIoeventtype type; FinalBlockingqueue<selectionkey>Pollqueue; if(isinputevents) {type=Ioeventtype.read; Pollqueue=Inpollqueue; } Else{type=NULL; Pollqueue=NULL; } if(Pollqueue = =NULL) { return NULL; } Try { //set a timeout of 1 seconds so that when the I/O queue is emptied after shutting down, it does not cause//Demultiplexor has been blocked .Selectionkey key = Pollqueue.poll (1000L, Timeunit.milliseconds); if(Key! =NULL) { if(Key.attachment ()instanceofphysicalconnection) { return NewIoevent<physicalconnection>( type, (physicalconnection) (Key.attachment ())); } } } Catch(interruptedexception e) {//Ignore } return NULL; }
So much for the processing of the new socket.
"Write a common server program in Java" 03 processing a new socket