流程1 :在ServerBootstrap(AbstractBootstrap<B,C>).bind(int) 绑定端口。
1、ServerBootstrap(AbstractBootstrap<B,C>).initAndRegister() 创建一个ServerSocketChannel ,并注册到EventLoop中。
在init时,主要通过工厂方法创建一个ServerSocketChannel ,并初始化。ServerBootstrap.init(Channel)
在init方法里面主要在PipeLine中增加了一个ServerBootstrapAcceptor ,用来处理新连接。
2、 NioEventLoopGroup(MultithreadEventLoopGroup).register(Channel) 把ServerSocketChannel注册到EventLoop 中,并返回一个ChannelFuture .
EventLoop 与ServerSocketChannel 的关系主要由io.netty.util.concurrent.EventExecutorChooserFactory 类来决定。
当EventLoop与ServerSocketChannel关联建立之后。实际执行register代码如下:
@Override
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
if (eventLoop == null) {
throw new NullPointerException("eventLoop");
}
if (isRegistered()) {
promise.setFailure(new IllegalStateException("registered to an event loop already"));
return;
}
if (!isCompatible(eventLoop)) {
promise.setFailure(
new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));
return;
}
AbstractChannel.this.eventLoop = eventLoop;
if (eventLoop.inEventLoop()) {
register0(promise);
} else {
try {
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
} catch (Throwable t) {
logger.warn(
"Force-closing a channel whose registration task was not accepted by an event loop: {}",
AbstractChannel.this, t);
closeForcibly();
closeFuture.setClosed();
safeSetFailure(promise, t);
}
}
}
此时,为main线程调用register方法,所以通过eventLoop 来执行register任务。
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
实际注册ServerSocketChannel的堆栈如下:
ServerBootstrap$1.initChannel(Channel) line: 172
ServerBootstrap$1(ChannelInitializer<C>).initChannel(ChannelHandlerContext) line: 113
ServerBootstrap$1(ChannelInitializer<C>).handlerAdded(ChannelHandlerContext) line: 105
DefaultChannelPipeline.callHandlerAdded0(AbstractChannelHandlerContext) line: 597
DefaultChannelPipeline.access$000(DefaultChannelPipeline, AbstractChannelHandlerContext) line: 44
DefaultChannelPipeline$PendingHandlerAddedTask.execute() line: 1387
DefaultChannelPipeline.callHandlerAddedForAllHandlers() line: 1122
DefaultChannelPipeline.invokeHandlerAddedIfNeeded() line: 647
AbstractNioMessageChannel$NioMessageUnsafe(AbstractChannel$AbstractUnsafe).register0(ChannelPromise) line: 506
AbstractChannel$AbstractUnsafe.access$200(AbstractChannel$AbstractUnsafe, ChannelPromise) line: 419
AbstractChannel$AbstractUnsafe$1.run() line: 478
会执行ServerBootstrap$1.initChannel(Channel) 方法添加ServerBootstrapAcceptor 。
流程2: EventLoop.run() 线程执行select()方法,等待新链接的到来。
SelectedSelectionKeySetSelector.select(long) line: 62
NioEventLoop.select(boolean) line: 752
NioEventLoop.run() line: 408
SingleThreadEventExecutor$5.run() line: 858
DefaultThreadFactory$DefaultRunnableDecorator.run() line: 138
流程3: EventLoop.run() 执行select()时,遇到accept事件,调用ServerBootstrapAcceptor.read()事件。
ServerBootstrap$ServerBootstrapAcceptor.channelRead(ChannelHandlerContext, Object) line: 244
DefaultChannelHandlerContext(AbstractChannelHandlerContext).invokeChannelRead(Object) line: 362
AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext, Object) line: 348
DefaultChannelHandlerContext(AbstractChannelHandlerContext).fireChannelRead(Object) line: 340
LoggingHandler.channelRead(ChannelHandlerContext, Object) line: 241
DefaultChannelHandlerContext(AbstractChannelHandlerContext).invokeChannelRead(Object) line: 362
AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext, Object) line: 348
DefaultChannelPipeline$HeadContext(AbstractChannelHandlerContext).fireChannelRead(Object) line: 340
DefaultChannelPipeline$HeadContext.channelRead(ChannelHandlerContext, Object) line: 1334
DefaultChannelPipeline$HeadContext(AbstractChannelHandlerContext).invokeChannelRead(Object) line: 362
AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext, Object) line: 348
DefaultChannelPipeline.fireChannelRead(Object) line: 926
AbstractNioMessageChannel$NioMessageUnsafe.read() line: 93
NioEventLoop.processSelectedKey(SelectionKey, AbstractNioChannel) line: 644
NioEventLoop.processSelectedKeysOptimized() line: 579
NioEventLoop.processSelectedKeys() line: 496
NioEventLoop.run() line: 458
SingleThreadEventExecutor$5.run() line: 858
DefaultThreadFactory$DefaultRunnableDecorator.run() line: 138
FastThreadLocalThread(Thread).run() line: 745
ServerBootstrapAcceptor 事件,主要做一件事件,那就是把childGroup 和SocketChannel 相关联。 之后,读取写入数据就交由EventLoop来处理。
public void channelRead(ChannelHandlerContext ctx, Object msg) {
final Channel child = (Channel) msg;
child.pipeline().addLast(childHandler);
setChannelOptions(child, childOptions, logger);
for (Entry<AttributeKey<?>, Object> e: childAttrs) {
child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
}
try {
childGroup.register(child).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
forceClose(child, future.cause());
}
}
});
} catch (Throwable t) {
forceClose(child, t);
}
}
在EventLoop 调用select方法时,
// Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead
// to a spin loop
if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
unsafe.read();
}
@Override
protected int doReadMessages(List<Object> buf) throws Exception {
SocketChannel ch = SocketUtils.accept(javaChannel());
try {
if (ch != null) {
buf.add(new NioSocketChannel(this, ch));
return 1;
}
} catch (Throwable t) {
logger.warn("Failed to create a new channel from an accepted socket.", t);
try {
ch.close();
} catch (Throwable t2) {
logger.warn("Failed to close a socket.", t2);
}
}
return 0;
}
List<Object> buf 为缓冲区,但是添加了NioSocketChannel.