Весь следующий код от Netty4.0.31.Final. Канал ServerBootstrap
- NioServerSocketChannel
.Возможно ли, что execute.fireChannelActive() выполняется дважды при выполнении ServerBootstrap.bind()?
Основная логика 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()
также могут быть выполнены здесь.
Итак, есть ли возможность, что pipeline.fireChannelActive()
выполняется дважды при создании и привязке одного NioServerSocketChannel
?
Да, я не знаю ответа нет в настоящее время. Но ключевой момент (или другое объяснение) заключается в том, что 'AbstractUnsafe.register0 (ChannelPromise promise)' и 'AbstractUnsafe.bind (SocketAddress, ChannelPromise)' оба исполняются EventLoop. 'AbstractUnsafe.register0 (обещание ChannelPromise)' выполняется до 'AbstractUnsafe.bind (SocketAddress, ChannelPromise)', поэтому 'isActive()' вернет false в 'AbstractUnsafe.register0 (обещание ChannelPromise)'. – labmem