NioSocketAcceptor初始化

一、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这个比较重要的方法,下面我们来看看在这个方法中,我们坐了些什么?


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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值