Netty 注册Channel解析

关系图

图一.jpg

调用链路

图二.jpg

源码片段

AbstractBootstrap#initAndRegister

ChannelFuture regFuture = config().group().register(channel);

SingleThreadEventLoop#register(Channel)

AbstractChannel.AbstractUnsafe#register

// 省略...
AbstractChannel.this.eventLoop = eventLoop;  

if (eventLoop.inEventLoop()) {  
    register0(promise);  
} else {  
    try {  
        eventLoop.execute(new Runnable() {  
            @Override  
  public void run() {  
                register0(promise);  
  }  
        });  
  } catch (Throwable t) {  
        logger.warn(  
                "Force-closing a channel whose registration task was not accepted by an event loop: {}",  
  AbstractChannel.this, t);  
  closeForcibly();  
  closeFuture.setClosed();  
  safeSetFailure(promise, t);  
  }  
}

调用AbstractChannel.AbstractUnsafe#register0

// ...
doRegister();
// ...
pipeline.invokeHandlerAddedIfNeeded();  
safeSetSuccess(promise); 
pipeline.fireChannelRegistered();

调用AbstractNioChannel#doRegister

@Override  
protected void doRegister() throws Exception {  
    boolean selected = false;  
 for (;;) {  
        try {  
        // 注册事件,Channel作为一个附加对象attachment
            selectionKey = javaChannel().register(eventLoop().selector, 0, this);  
 return;  } catch (CancelledKeyException e) {  
            if (!selected) {  
                // Force the Selector to select now as the "canceled" SelectionKey may still be  
               // cached and not removed because no Select.select(..) operation was called yet.                     eventLoop().selectNow();  
                selected = true;  
              } else {  
                // We forced a select operation on the selector before but the SelectionKey is still cached  
             // for whatever reason. JDK bug ? 
                  throw e;  
              }  
        }  
    }  
}

总结

调用register()方法注册selector,Netty将底层Channel注册到事件轮询器selector上,并把Netty的服务端Channel作为一个附加对象attachment。

添加新评论