NOTE

4. Bind the Server Port

Call path, AbstractBootstrap, AbstractUnsafe, and AbstractNioChannel

JavaCreated Updated 1 min readhistorical

This is a historical learning note and may contain outdated or incomplete understanding.

Call Path

bind

  • doBind
  • initAndRegister
  • channelFactory.newChannel()
  • init(channel)
  • ChannelFuture regFuture = config().group().register(channel);
  • doBind0(regFuture, channel, localAddress, promise); — this is the part to focus on.

AbstractBootstrap

private static void doBind0(
        final ChannelFuture regFuture, final Channel channel,
        final SocketAddress localAddress, final ChannelPromise promise) {

    // This method is invoked before channelRegistered() is triggered.  Give user handlers a chance to set up
    // the pipeline in its channelRegistered() implementation.
    channel.eventLoop().execute(new Runnable() {
        @Override
        public void run() {
            if (regFuture.isSuccess()) {
                // Call AbstractChannel.bind,
                // then DefaultChannelPipeline.bind,
                // then AbstractChannelHandlerContext#bind,
                // and finally AbstractChannel.AbstractUnsafe#bind.
                channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
            } else {
                promise.setFailure(regFuture.cause());
            }
        }
    });
}

AbstractUnsafe

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

    // Call the low-level JDK bind.
    // javaChannel().bind(localAddress, config.getBacklog());
    doBind(localAddress);


    if (!wasActive && isActive()) {
        invokeLater(new Runnable() {
            @Override
            public void run() {
                // Call channelActive on every InboundHandler in the pipeline.
                // The first handler is DefaultChannelPipeline.HeadContext.
                pipeline.fireChannelActive();
            }
        });
    }

    safeSetSuccess(promise);
}

io.netty.channel.DefaultChannelPipeline.HeadContext#channelActive

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

    readIfIsAutoRead();// key point
    // This calls channel.read -> pipeline.read -> tail.read -> ChannelOutboundHandler.read ->
    // io.netty.channel.AbstractChannel.AbstractUnsafe#beginRead
    // -> io.netty.channel.nio.AbstractNioChannel#doBeginRead
}

AbstractNioChannel

protected void doBeginRead() throws Exception {
    // Channel.read() or ChannelHandlerContext.read() was called
    // Obtain the SelectionKey.
    final SelectionKey selectionKey = this.selectionKey;
    if (!selectionKey.isValid()) {
        return;
    }

    readPending = true;

    final int interestOps = selectionKey.interestOps();
    if ((interestOps & readInterestOp) == 0) {
        // Add the read event: the accept event.
        selectionKey.interestOps(interestOps | readInterestOp);

    }
}

Discussion

Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub