以下所有代码均来自Netty4.0.31.Final。 ServerBootstrap
的频道是NioServerSocketChannel
。执行ServerBootstrap.bind()时pipeline.fireChannelActive()会执行两次吗?
的ServerBootstrap.bind(int)
的主要逻辑是AbstractBootstrap.doBind(SocketAddress)
:
private ChannelFuture doBind(final SocketAddress localAddress) {
final ChannelFuture regFuture = initAndRegister();
...
if (regFuture.isDone()) {
...
doBind0(regFuture, channel, localAddress, promise);
...
} else {
regFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
...
doBind0(regFuture, channel, localAddress, promise);
}
});
}
}
在initAndRegister()
的代码终于进入AbstractUnsafe.register0(ChannelPromise promise)
:
private void register0(ChannelPromise promise) {
try {
...
boolean firstRegistration = neverRegistered;
doRegister();
...
if (firstRegistration && isActive()) {
pipeline.fireChannelActive();
}
} catch (Throwable t) {
...
}
}
正如你所看到的,pipeline.fireChannelActive()
可在此执行。
让我们回到AbstractBootstrap.doBind(SocketAddress)
,在doBind0(regFuture, channel, localAddress, promise)
代码终于进入AbstractUnsafe.bind(SocketAddress,ChannelPromise)
:
public final void bind(final SocketAddress localAddress, final ChannelPromise promise) {
...
boolean wasActive = isActive();
try {
doBind(localAddress);
} catch (Throwable t) {
...
}
if (!wasActive && isActive()) {
invokeLater(new OneTimeTask() {
@Override
public void run() {
pipeline.fireChannelActive();
}
});
}
...
}
正如你所看到的,pipeline.fireChannelActive()
也可以在此执行。
那么,在创建并绑定一个NioServerSocketChannel
时,有没有可能执行pipeline.fireChannelActive()
?
是的,我知道答案是否定的现在。但关键点(或另一种解释)是'AbstractUnsafe.register0(ChannelPromise promise)'和'AbstractUnsafe.bind(SocketAddress,ChannelPromise)'都由EventLoop执行。 'AbstractUnsafe.register0(ChannelPromise promise)'在'AbstractUnsafe.bind(SocketAddress,ChannelPromise)'之前执行,所以'AbstractAnsafe.register0(ChannelPromise promise)'中的isActive()'将返回false。 – labmem