Netty server Startup (1) creates and initializes a channel

Register the selector

To summarize, we have done these things

  • Setting up eventLoop (for thread binding)
  • Call the register method of the underlying SelectableChannel class in the JDK to register
  • Trigger a callback added to a channel by a handler that triggers a channel registration success event

The process of registering a selector is in the register method on the config().group().register(channel) line, which eventually calls the AbstractChannel#register method

public final void register(EventLoop eventLoop, final ChannelPromise promise) {
    ObjectUtil.checkNotNull(eventLoop, "eventLoop");
    // Omit some code

    AbstractChannel.this.eventLoop = eventLoop;
  if (eventLoop.inEventLoop()) {  register0(promise);  } else {  try {  eventLoop.execute(new Runnable() {  @Override  public void run(a) {  register0(promise);  }  });  } catch (Throwable t) {  / / to omit  }  } } Copy the code

As you can see, you’re setting up the EventLoop (for binding threads), and look at the method register0 that actually registers

private void register0(ChannelPromise promise) {
    try {

        if(! promise.setUncancellable() || ! ensureOpen(promise)) {            return;
 }  //neverRegistered starts with true  boolean firstRegistration = neverRegistered;  doRegister();  neverRegistered = false;  registered = true;   // Triggers a callback when a handler is added to a channel  pipeline.invokeHandlerAddedIfNeeded();   safeSetSuccess(promise);  // Propagate the channel registration success event  pipeline.fireChannelRegistered();   if (isActive()) {  / / to omit  }  } catch (Throwable t) {  / / to omit  } } Copy the code

As you can see, the doRegister method is called, and the AbstractNioChannel#doRegister method is called

protected void doRegister(a) throws Exception {
    boolean selected = false;
    for (;;) {
        try {
            //javaChannel() returns the Java underlying SelectableChannel
 // The register method binds netty's channel to the underlying JDK channel as an attachment  selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0.this);  return;  } catch (CancelledKeyException e) {  / / to omit  }  } } Copy the code

As you can see, this is a call to the Java underlying method to register

Port binding

To summarize, we have done the following things

  • Call the JDK’s underlying bind method for port binding
  • The channelActive event is triggered
  • Trigger the read event, register the Accept event with selector

Port binding is in the AbstractBootstrap#doBind0 method

private static void doBind0(
    final ChannelFuture regFuture, final Channel channel,
    final SocketAddress localAddress, final ChannelPromise promise) {
    
    channel.eventLoop().execute(new Runnable() {
 @Override  public void run(a) {  if (regFuture.isSuccess()) {  channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);  } else {  promise.setFailure(regFuture.cause());  }  }  }); } Copy the code

This is where you end up calling the AbstractChannel#bind method

public final void bind(final SocketAddress localAddress, final ChannelPromise promise) {
    assertEventLoop();

    // Omit some code

 boolean wasActive = isActive();  try {  // Call the underlying JDK for binding  doBind(localAddress);  } catch (Throwable t) {  safeSetFailure(promise, t);  closeIfClosed();  return;  }   if(! wasActive && isActive()) { invokeLater(new Runnable() {  @Override  public void run(a) {  // Send the channelActive event  pipeline.fireChannelActive();  }  });  }   safeSetSuccess(promise); } Copy the code

Following the doBind method, the NioServerSocketChannel#doBind method is called

protected void doBind(SocketAddress localAddress) throws Exception {
    if (PlatformDependent.javaVersion() >= 7) {
        javaChannel().bind(localAddress, config.getBacklog());
    } else {
        javaChannel().socket().bind(localAddress, config.getBacklog());
 } } Copy the code

You can see that you are calling the underlying JDK bind method

FireChannelActive finally calls the DefaultChannelPipeline#channelActive method

public void channelActive(ChannelHandlerContext ctx) {
    ctx.fireChannelActive();

    readIfIsAutoRead();
}
Copy the code

The AbstractNioChannel#doBeginRead method is called by the readIfIsAutoRead method

protected void doBeginRead(a) throws Exception {
    // Channel.read() or ChannelHandlerContext.read() was called
    final SelectionKey selectionKey = this.selectionKey;
    if(! selectionKey.isValid()) {        return;
 }   readPending = true;   final int interestOps = selectionKey.interestOps();  if ((interestOps & readInterestOp) == 0) {  selectionKey.interestOps(interestOps | readInterestOp);  } } Copy the code

As you can see, we’re registering the accept event with the selector. (See the previous NioServerSocketChannel constructor passed selectionkey.op_accept.)