次のコードはすべてNetty4.0.31.Finalのものです。 ServerBootstrap
さんのチャンネルはNioServerSocketChannel
です。ServerBootstrap.bind()の実行時にpipeline.fireChannelActive()が2回実行される可能性はありますか?
ServerBootstrap.bind(int)
のメインロジックはAbstractBootstrap.doBind(SocketAddress)
である:initAndRegister()
で
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);
}
});
}
}
コードが最終的に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()
が2回実行される可能性はありますか?
はい、私は答えは今は知っているん。しかし、要点(または別の説明)は、 'AbstractUnsafe.register0(ChannelPromise promise)'と 'AbstractUnsafe.bind(SocketAddress、ChannelPromise)'はどちらもEventLoopによって実行されるということです。 'AbstractUnsafe.register0(ChannelPromise promise)'は 'AbstractUnsafe.bind(SocketAddress、ChannelPromise)'の前に実行されるため、 'isActive()'は 'AbstractUnsafe.register0(ChannelPromise promise)'でfalseを返します。 – labmem