Go to: mina2.0 framework source code analysis (7)

Source: Internet
Author: User

We have finished the org. Apache. Mina. Core. session package. Now we start to enter the org. Apache. Mina. Core. Polling package. This package contains a base class that implements a round-robin policy (such as select call of NiO or other types of I/O round-robin system calls (such as epoll, poll, kqueue, etc.

Let's take a look at the abstract base class abstractpollingioacceptor, which inherits from abstractioacceptor. The two generic parameters are the session to be processed and the socket connection to the server. The underlying sockets will be constantly detected, and will be awakened to process any socket that needs to be processed. This class encapsulates the bind, accept, and dispose actions of the server socket. Its member variable executor is responsible for accepting connection requests from the client, and the other abstractpollingioprocessor is used to process client I/O operation requests, such as reading/writing and closing connections.

The most important member variables are:

Private Final queue <acceptoroperationfuture> registerqueue = new concurrent1_queue <acceptoroperationfuture> (); // register a queue
Private Final queue <acceptoroperationfuture> cancelqueue = new concurrent1_queue <acceptoroperationfuture> (); // cancel the registration queue
Private final map <socketaddress, h> boundhandles = collections
. Synchronizedmap (New hashmap <socketaddress, h> (); // ing table from local address to server socket

Let's take a look at the processing process after the server calls BIND:

Protected final set <socketaddress> bind0 (
List <? Extends socketaddress> localaddresses) throws exception {
Acceptoroperationfuture request = new acceptoroperationfuture (localaddresses); // register the request
Registerqueue. Add (request); // join the registration queue and wait for worker to process
// Create a worker instance to start working
Startupworker ();
Wakeup ();
Request. awaituninterruptibly ();
// Update the local binding address
Set <socketaddress> newlocaladdresses = new hashset <socketaddress> ();
For (H handle: boundhandles. Values ()){
Newlocaladdresses. Add (localaddress (handle ));
}
Return newlocaladdresses;
}

The worker thread is responsible for receiving client requests,

Private class worker implements runnable {
Public void run (){
Int nhandles = 0;
While (selectable ){
Try {
// Detect if we have some keys ready to be processed
Boolean selected = select (); // checks whether there is a selectionkey that can be processed
Nhandles + = registerhandles (); // register the sockets handle of the server. In this way, set the selector status to op_accept and bind it to the listening port, indicates that the connection request from the client is accepted,
If (selected ){
Processhandles (selectedhandles (); // process the server socket handle set in which the selectionkey status that can be processed is op_accept (that is, the server actually processes connection requests from the client)
}
Nhandles-= unregisterhandles (); // check whether there is a client request to cancel the connection
If (nhandles = 0 ){
Synchronized (LOCK ){
If (registerqueue. isempty ()
& Amp; cancelqueue. isempty () {// complete the work
Worker = NULL;
Break;
}
}
}
} Catch (throwable e ){
Exceptionmonitor. getinstance (). exceptioncaught (E );
Try {
Thread. Sleep (1000); // The thread sleeps for one second.
} Catch (interruptedexception E1 ){
Exceptionmonitor. getinstance (). exceptioncaught (E1 );
}
}
}
If (selectable & isdisposing () {// release resources
Selectable = false;
Try {
If (createdprocessor ){
Processor. Dispose ();
}
} Finally {
Try {
Synchronized (disposallock ){
If (isdisposing ()){
Destroy ();
}
}
} Catch (exception e ){
Exceptionmonitor. getinstance (). exceptioncaught (E );
} Finally {
Disposalfuture. setdone ();
}
}
}
}
Private int registerhandles () {// register the server sockets handle
For (;;){
Acceptoroperationfuture future = registerqueue. Poll ();
Map <socketaddress, h> newhandles = new hashmap <socketaddress, h> ();
List <socketaddress> localaddresses = Future. getlocaladdresses ();
Try {
For (socketaddress A: localaddresses ){
H handle = open (A); // open the specified address and return the server socket handle.
Newhandles. Put (localaddress (handle), handle); // Add the address to the server socket ing table
}
Boundhandles. putall (newhandles); // update the local bound address set
// And configure y.
Future. setdone (); // complete the registration process
Return newhandles. Size ();
} Catch (exception e ){
Future. setexception (E );
} Finally {
// Roll back if failed to bind all addresses.
If (future. getexception ()! = NULL ){
For (H handle: newhandles. Values ()){
Try {
Close (handle); // close the server socket handle
} Catch (exception e ){
Exceptionmonitor. getinstance (). exceptioncaught (E );
}
}
Wakeup ();
}
}
}
}
Private void processhandles (iterator While (handles. hasnext ()){
H handle = handles. Next ();
Handles. Remove ();
T session = accept (processor, handle); // handle is a server socket handle that actually receives requests from the client and returns the session on the given associated processor.
If (session = NULL ){
Break;
}
Finishsessioninitialization (Session, null, null); // end Session Initialization
// Add the session to the socketioprocessor
Session. getprocessor (). Add (session );
}
}
}

It is worth noting that the wakeup method is used to interrupt the select method. It needs to be called when the registration queue or cancellation queue changes, see the implementation of a subclass niosocketacceptor of this class:

Protected Boolean select () throws exception {
Return selector. Select ()> 0;
}
Protected void wakeup (){
Selector. Wakeup ();
}

We can refer to the JDK documentation, which explains the select method of selector as follows: select a group of keys and the corresponding channel is ready for I/O operations. This method is executedIn blocking modeSelect Operation. This method is returned only when at least one channel is selected, the wakeup method that calls this selector, the current thread is interrupted, or the specified timeout period expires (whichever comes first.

References

1 ,《Java NiO non-blocking server example"

 

Author: phinecos)
Source: http://phinecos.cnblogs.com/
The copyright of this article is shared by the author and the blog Park. You are welcome to repost it, but please keep this statement and provide the original article connection clearly on the article page.

Author: Dongting sangren

Source: http://phinecos.cnblogs.com/

This blog complies with the Creative Commons Attribution 3.0 License. If it is used for non-commercial purposes, you can reprint it freely, but please keep the original author information and article URL.

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.