2016-11-08 386 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