一、Acceptor初始化
1. new NIOSocketAccptor()
在NioSocketAcceptor中,初始化Acceptor的时候,我们会同时创建NIOProcessor
public NioSocketAcceptor() {
super(new DefaultSocketSessionConfig(), NioProcessor.class);
((DefaultSocketSessionConfig) getSessionConfig()).init(this);
}
2.在NioSocketAcceptor父类AbstractPollingIoAcceptor中,我们会创建一个NIOProcessor池(new SimpleIoProcessorPool<S>(processorClass)),创建NIOProcess
protected AbstractPollingIoAcceptor(IoSessionConfig sessionConfig, Class<? extends IoProcessor<S>> processorClass) {
this(sessionConfig, null, new SimpleIoProcessorPool<S>(processorClass), true);
}
3. 在SimpleIoProcessorPool中,
我们会调用 构造器产生DEFAULT_SIZE(DEFAULT_SIZE=cpu个数加1)个NIOProcessor
public SimpleIoProcessorPool(Class<? extends IoProcessor<S>> processorType) {
this(processorType, null, DEFAULT_SIZE);
}
并为每个processor产生一个线程池
if (createdExecutor) {
this.executor = Executors.newCachedThreadPool();
// Set a default reject handler
}
4 回到AbstractIoService中,会创建一个监听者,添加serviceActivationListener
// Create the listeners, and add a first listener : a activation listener
// for this service, which will give information on the service state.
listeners = new IoServiceListenerSupport(this);
listeners.add(serviceActivationListener);
同时,我们会创建一个线程池
if (executor == null) {
this.executor = Executors.newCachedThreadPool();
createdExecutor = true;
} else {
this.executor = executor;
createdExecutor = false;
}
5. 在AbstractPollingIoAcceptor中,会调用NioSocketAcceptor的Init方法打开Selector
protected void init() throws Exception {
selector = Selector.open();
}
二. 绑定地址
1.前面不太重要的我们都省略了,我们来看看比较重要的,在AbstractPollingIoAcceptor中。我们会调用bindInternal这个方法。在这个方法中,会调用startupAcceptor这个比较重要的方法,下面我们来看看在这个方法中,我们坐了些什么?
那我们来看看这个线程:
在AbstractPollingIoAcceptor的registerHandles方法中,我们会调用一个NIOSocketAcceptor 中的open方法来进行对channel的注册:请看线面的代码:
在processHandles中, 当接收到请求时调用accept()方法法处理接收连接,把SocektChannel绑定到NioSession中。
1. new NIOSocketAccptor()
在NioSocketAcceptor中,初始化Acceptor的时候,我们会同时创建NIOProcessor
public NioSocketAcceptor() {
super(new DefaultSocketSessionConfig(), NioProcessor.class);
((DefaultSocketSessionConfig) getSessionConfig()).init(this);
}
2.在NioSocketAcceptor父类AbstractPollingIoAcceptor中,我们会创建一个NIOProcessor池(new SimpleIoProcessorPool<S>(processorClass)),创建NIOProcess
protected AbstractPollingIoAcceptor(IoSessionConfig sessionConfig, Class<? extends IoProcessor<S>> processorClass) {
this(sessionConfig, null, new SimpleIoProcessorPool<S>(processorClass), true);
}
3. 在SimpleIoProcessorPool中,
我们会调用 构造器产生DEFAULT_SIZE(DEFAULT_SIZE=cpu个数加1)个NIOProcessor
public SimpleIoProcessorPool(Class<? extends IoProcessor<S>> processorType) {
this(processorType, null, DEFAULT_SIZE);
}
并为每个processor产生一个线程池
if (createdExecutor) {
this.executor = Executors.newCachedThreadPool();
// Set a default reject handler
}
4 回到AbstractIoService中,会创建一个监听者,添加serviceActivationListener
// Create the listeners, and add a first listener : a activation listener
// for this service, which will give information on the service state.
listeners = new IoServiceListenerSupport(this);
listeners.add(serviceActivationListener);
同时,我们会创建一个线程池
if (executor == null) {
this.executor = Executors.newCachedThreadPool();
createdExecutor = true;
} else {
this.executor = executor;
createdExecutor = false;
}
5. 在AbstractPollingIoAcceptor中,会调用NioSocketAcceptor的Init方法打开Selector
protected void init() throws Exception {
selector = Selector.open();
}
二. 绑定地址
1.前面不太重要的我们都省略了,我们来看看比较重要的,在AbstractPollingIoAcceptor中。我们会调用bindInternal这个方法。在这个方法中,会调用startupAcceptor这个比较重要的方法,下面我们来看看在这个方法中,我们坐了些什么?
private void startupAcceptor() throws InterruptedException {
// If the acceptor is not ready, clear the queues
// TODO : they should already be clean : do we have to do that ?
if (!selectable) {
registerQueue.clear();
cancelQueue.clear();
}
// start the acceptor if not already started
Acceptor acceptor = acceptorRef.get();
if (acceptor == null) {
lock.acquire();
acceptor = new Acceptor();//我们在AbstractPollingIoAcceptor中创建了Acceptor这个线程,这个就是创建channel通道的一个线程。
if (acceptorRef.compareAndSet(null, acceptor)) {
executeWorker(acceptor);
} else {
lock.release();
}
}
}
那我们来看看这个线程:
private class Acceptor implements Runnable {
public void run() {
assert (acceptorRef.get() == this);
int nHandles = 0;
// Release the lock
lock.release();
while (selectable) {
try {
// Detect if we have some keys ready to be processed
// The select() will be woke up if some new connection
// have occurred, or if the selector has been explicitly
// woke up
int selected = select();
// this actually sets the selector to OP_ACCEPT,
// and binds to the port on which this class will
// listen on
//我们将在下面对registerHandles进行分析
nHandles += registerHandles();
// Now, if the number of registred handles is 0, we can
// quit the loop: we don't have any socket listening
// for incoming connection.
if (nHandles == 0) {
acceptorRef.set(null);
if (registerQueue.isEmpty() && cancelQueue.isEmpty()) {
assert (acceptorRef.get() != this);
break;
}
if (!acceptorRef.compareAndSet(null, this)) {
assert (acceptorRef.get() != this);
break;
}
assert (acceptorRef.get() == this);
}
if (selected > 0) {
// We have some connection request, let's process
// them here.
processHandles(selectedHandles());
}
// check to see if any cancellation request has been made.
nHandles -= unregisterHandles();
} catch (ClosedSelectorException cse) {
// If the selector has been closed, we can exit the loop
break;
} catch (Throwable e) {
ExceptionMonitor.getInstance().exceptionCaught(e);
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
ExceptionMonitor.getInstance().exceptionCaught(e1);
}
}
}
// Cleanup all the processors, and shutdown the acceptor.
if (selectable && isDisposing()) {
selectable = false;
try {
if (createdProcessor) {
processor.dispose();
}
} finally {
try {
synchronized (disposalLock) {
if (isDisposing()) {
destroy();
}
}
} catch (Exception e) {
ExceptionMonitor.getInstance().exceptionCaught(e);
} finally {
disposalFuture.setDone();
}
}
}
}
/**
* This method will process new sessions for the Worker class. All
* keys that have had their status updates as per the Selector.selectedKeys()
* method will be processed here. Only keys that are ready to accept
* connections are handled here.
* <p/>
* Session objects are created by making new instances of SocketSessionImpl
* and passing the session object to the SocketIoProcessor class.
*/
@SuppressWarnings("unchecked")
private void processHandles(Iterator<H> handles) throws Exception {
while (handles.hasNext()) {
H handle = handles.next();
handles.remove();
// 让一个新的请求和processor相关联,
// 并且返回一个session
S session = accept(processor, handle);
if (session == null) {
continue;
}
initSession(session, null, null);
// 添加session到NIOSocketProcessor
session.getProcessor().add(session);
}
}
}
在AbstractPollingIoAcceptor的registerHandles方法中,我们会调用一个NIOSocketAcceptor 中的open方法来进行对channel的注册:请看线面的代码:
protected ServerSocketChannel open(SocketAddress localAddress) throws Exception {
// Creates the listening ServerSocket
ServerSocketChannel channel = ServerSocketChannel.open();
boolean success = false;
try {
// This is a non blocking socket channel
channel.configureBlocking(false);
// Configure the server socket,
ServerSocket socket = channel.socket();
// Set the reuseAddress flag accordingly with the setting
socket.setReuseAddress(isReuseAddress());
// and bind.
socket.bind(localAddress, getBacklog());
// Register the channel within the selector for ACCEPT event
channel.register(selector, SelectionKey.OP_ACCEPT);
success = true;
} finally {
if (!success) {
close(channel);
}
}
return channel;
}
在processHandles中, 当接收到请求时调用accept()方法法处理接收连接,把SocektChannel绑定到NioSession中。
protected NioSession accept(IoProcessor<NioSession> processor, ServerSocketChannel handle) throws Exception {
SelectionKey key = handle.keyFor(selector);
if ((key == null) || (!key.isValid()) || (!key.isAcceptable())) {
return null;
}
// accept the connection from the client
SocketChannel ch = handle.accept();
if (ch == null) {
return null;
}
return new NioSocketSession(this, processor, ch);
}