Starting from a simple server hander analysis of Xsocket, first define a simple Echohandler inheritance Idatahandler
Public class Implements idatahandler{ publicboolean onData (inonblockingconnection NBC) Throws IOException, bufferunderflowexception, maxreadsizeexceededexception { = Nbc.readstringbydelimiter ("\ r \ n"); + "\ r \ n"); return true ; }}
Then use this idatahandler to start the server
Public classXsockettest { Public Static voidMain (string[] args)throwsunknownhostexception, IOException {//TODO auto-generated Method StubIServer SRV =NewServer (8090,NewEchohandler ()); //run it within the current thread.Srv.run ();//The call would not return//... or start it by using a dedicated thread//Srv.start ();//returns after the server has been started }}
This implements a server that sends a string sent by the client back to the client, and the interface is simple.
Starting with the construction of the server, the server inherits from Iserver, and the class description is to receive the new connection, and the Inonblockingconnection processing agent to the Handler assigned to the server. The server contains dispatcher,dispatcher is responsible for performing IO operations, and each connection is assigned to a dispatcher. To handle application-related events such as OnData, onconnected, and so on, the corresponding callback function of the server's handler is called. During the server startup phase, the callback functions supported by handler are parsed by reflection, and the callback functions are tagged by implementing different interfaces such as Iconnecthandler, Idatahandler, and so on. Typically a server handler implements multiple handler interfaces. This section describes the overall structure of the xsocket, the main concepts are discussed, the latter will be detailed analysis.
The server overloads more than one constructor, which constructs the method called
protectedServer (inetsocketaddress address, map<string, object> options, Ihandler handler, Sslcontext Sslcontext,BooleanSslon,intBacklogintMinpoolsize,intMaxpoolsize,intTaskqueuesize)throwsunknownhostexception, IOException {defaultworkerpool=NewWorkerpool (minpoolsize, Maxpoolsize, taskqueuesize); Workerpool=Defaultworkerpool; if(Sslcontext! =NULL) {acceptor= Connectionutils.getioprovider (). Createacceptor (NewLifecyclehandler (), address, backlog, options, Sslcontext, Sslon); } Else{acceptor= Connectionutils.getioprovider (). Createacceptor (NewLifecyclehandler (), address, backlog, options); } localhostname=acceptor.getlocaladdress (). GetHostName (); LocalPort=Acceptor.getlocalport (); SetHandler (handler); }
The main parameters are port, Ihandler, whether SSL is supported, working thread pool parameters, other than what we give are the default values. Creating a worker thread pool first Workpool,workerpool inheriting from the Threadpoolexecutor,workpool constructor requires a queue that holds the task before the task executes, and this is Workerpoolawarequeue Extends Linkedblockingqueue<runnable> This workerpoolawarequeue rewritten the offer function to join the log, A small optimization occurs when the online pool does not have idle threads and returns False when the maximum number of threads is not reached to force the start of a new worker thread instead of waiting in the task queue.
Then create the acceptor. This creates a lifecyclehandler (important, later), implements the Iioacceptorcallback interface, and defines the oncoonected () method in the interface to callback when the acceptor binds to the socket or receives the request. Connectionutils provides a handy way to set up and bytebuffer operations, where static variables Ioprovider define various parameters of the socket IO, createacceptor function calls
New Ioacceptor (callback, address, backlog, isreuseaddress);
The Ioacceptor constructor is as follows
PublicIoacceptor (Iioacceptorcallback callback, inetsocketaddress address,intBacklog, Sslcontext Sslcontext,BooleanSslon,Booleanisreuseaddress)throwsIOException { This. Callback =callback;//This callback is just said Lifecyclehandler This. Sslcontext =Sslcontext; This. Sslon =Sslon; Log.fine ("Try to bind server on" +address); //create a new server socketServerchannel =Serversocketchannel.open ();//Construction Serverchannelassert(Serverchannel! =NULL); Serverchannel.configureblocking (true); Serverchannel.socket (). Setsotimeout (0);//Accept method never times outServerchannel.socket (). setreuseaddress (isreuseaddress); Whether the port can be reused when the channel is closed but still aliveTry{serverchannel.socket (). Bind (address, backlog); Build Iosocketdispatcherpool Dispatcherpool=NewIosocketdispatcherpool ("SRV" +Getlocalport (), ioprovider.getserverdispatcherinitialsize ()); } Catch(Bindexception Be) {serverchannel.close (); Log.warning ("Could not bind server to" + Address + ". Reason: "+dataconverter.tostring (BE)); ThrowBe ; } }
Iosocketdispatcherpool was created in the constructor, and two iosocketdispatcher were instantiated and run when the pool was built
for(inti = currentrunning; i < size; i++) {Iounsynchronizedmemorymanager Memorymanager=NULL; if(preallocation) {
Memory management, using pre-allocated memory method first regardless of Memorymanager=Iounsynchronizedmemorymanager.createpreallocatedmemorymanager (preallocationsize, BufferMinsize, UseDirect); } Else{Memorymanager =Iounsynchronizedmemorymanager.createnonpreallocatedmemorymanager (Usedirect); } Iosocketdispatcher Dispatcher=NewIosocketdispatcher (Memorymanager, name + "#" +i); Dispatchers.addlast (dispatcher); Thread T=NewThread (Dispatcher); T.setdaemon (true); T.start (); for(Iiodispatcherpoollistener listener:listeners) {listener.ondispatcheradded (dispatcher); }}
The Iosocketdispatcher constructor called Selector = Selector.open (); The Run method is as follows
Public voidrun () {//set thread name and attach dispatcher ID to threadThread.CurrentThread (). SetName (name); Threadbound_id.set (ID); Direct_call_counter.set (0); if(Log.isloggable (level.fine)) {Log.fine ("Selector" + name + "Listening ..."); } intHandledtasks = 0; while(Isopen.get ()) {Try { intEventCount = Selector.select (5000); Handledtasks=performregisterhandlertasks ();//Handling registration tasks, important handledtasks+=performkeyupdatetasks ();//Handling key update tasks, importantif(EventCount > 0{Handlereadwritekeys ();//handling read-write events, important} handledtasks+=performderegisterhandlertasks (); Checkforlooping (EventCount+handledtasks, Lasttimewokeup); } Catch(Throwable e) {//eat and log exception if(Log.isloggable (level.fine)) {Log.fine ("[" + Thread.CurrentThread (). GetName () + "] exception occured while processing. Reason "+dataconverter.tostring (e)); } } } for(Iosockethandler sockethandler:getregistered ()) {sockethandler.onderegisteredevent (); } Try{selector.close (); } Catch(Exception e) {//eat and log exception if(Log.isloggable (level.fine)) {Log.fine ("Error occured by close selector within TearDown" +dataconverter.tostring (e)); } } }
Back to the original main method, where Srv.run () was called; The run function finally calls the accept function of acceptor
Private voidAccept () { while(Isopen.get ()) {Try { //Blocking Accept CallSocketchannel channel =serverchannel.accept (); //Create IosockethandlerIosocketdispatcher Dispatcher =Dispatcherpool.nextdispatcher (); Iochainablehandler Iohandler= Connectionutils.getioprovider (). Createiohandler (false, Dispatcher, channel, Sslcontext, Sslon); //Notify Call backcallback.onconnectionaccepted (Iohandler); Acceptedconnections++; } Catch(Exception e) {//If Acceptor is running (<socket>.close () causes this any//thread currently blocked in accept () would throw a socketexception) if(Serverchannel.isopen ()) {log.warning ("Error occured while accepting connection:" +dataconverter.tostring (e)); } } } }
It is important to complete the startup of the server, primarily starting a acceptor thread and two dispatcher threads.
Xsocket Analysis One, start