2016-11-08 388 views
0

以下所有代码均来自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()

回答

1

除非isActive能够在您指出的流程中将触发器从真到假再次翻转为真。我觉得它只能去积极的一次,所以假 - >真 - 从您的帖子>假

相关代码:

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(); 
+0

是的,我知道答案是否定的现在。但关键点(或另一种解释)是'AbstractUnsafe.register0(ChannelPromise promise)'和'AbstractUnsafe.bind(SocketAddress,ChannelPromise)'都由EventLoop执行。 'AbstractUnsafe.register0(ChannelPromise promise)'在'AbstractUnsafe.bind(SocketAddress,ChannelPromise)'之前执行,所以'AbstractAnsafe.register0(ChannelPromise promise)'中的isActive()'将返回false。 – labmem