以下所有代碼均來自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