执行ServerBootstrap.bind()时是否有可能执行两次pipeline.fireChannelActive()?

时间:2016-11-08 09:06:19

标签: netty

以下所有代码均来自Netty4.0.31.Final。 ServerBootstrap的频道为NioServerSocketChannel

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是否有可能被执行两次?

1 个答案:

答案 0 :(得分:1)

除非isActive能够在你指出的流程中再次将翻转从true翻转为假,再转为真。我认为它只能活跃一次,所以假 - >是的 - >假

您帖子中的相关代码:

boolean firstRegistration = neverRegistered;
...
if (firstRegistration && isActive()) {
    pipeline.fireChannelActive();  // isActive must be TRUE
}
...
boolean wasActive = isActive();
...
// If fireChannelActive was fired, then wasActive would be true, 
// preventing it from firing again
if (!wasActive && isActive()) {  
    invokeLater(new OneTimeTask() {
        @Override
        public void run() {
            pipeline.fireChannelActive();