Netty启动源码解析

Nio的方式启动一个服务端:

@Slf4j
public class Server {

    public static void main(String[] args) throws IOException {
        // 1. 创建 selector, 管理多个 channel
        Selector selector = Selector.open();
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);
        // 2. 建立 selector 和 channel 的联系(注册)
        // SelectionKey 就是将来事件发生后,通过它可以知道事件和哪个channel的事件
        SelectionKey sscKey = ssc.register(selector, 0, null);
        // key 只关注 accept 事件
        sscKey.interestOps(SelectionKey.OP_ACCEPT);
        log.debug("sscKey:{}", sscKey);
        ssc.bind(new InetSocketAddress(8080));
        while (true) {
            // 3. select 方法, 没有事件发生,线程阻塞,有事件,线程才会恢复运行
            // select 在事件未处理时,它不会阻塞, 事件发生后要么处理,要么取消,不能置之不理
            selector.select();
            // 4. 处理事件, selectedKeys 内部包含了所有发生的事件
            Iterator<SelectionKey> iter = selector.selectedKeys().iterator(); // accept, read
            while (iter.hasNext()) {
                SelectionKey key = iter.next();
                // 处理key 时,要从 selectedKeys 集合中删除,否则下次处理就会有问题
                iter.remove();
                log.debug("key: {}", key);
                // 5. 区分事件类型
                if (key.isAcceptable()) { // 如果是 accept
                    ServerSocketChannel channel = (ServerSocketChannel) key.channel();
                    SocketChannel sc = channel.accept();
                    sc.configureBlocking(false);

                    SelectionKey scKey = sc.register(selector, 0, null);
                    scKey.interestOps(SelectionKey.OP_READ);
                    log.debug("{}", sc);
                    log.debug("scKey:{}", scKey);
                } else if (key.isReadable()) { // 如果是 read
                    try {
                        SocketChannel channel = (SocketChannel) key.channel(); // 拿到触发事件的channel
                        ByteBuffer buffer = ByteBuffer.allocate(4);
                        int read = channel.read(buffer); // 如果是正常断开,read 的方法的返回值是 -1
                        if(read == -1) {
                            key.cancel();
                        } else {
                            buffer.flip();
                            System.out.println(Charset.defaultCharset().decode(buffer));
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                        key.cancel();  // 因为客户端断开了,因此需要将 key 取消(从 selector 的 keys 集合中真正删除 key)
                    }
                }
            }
        }
    }
}

在nio中有几个比较重要的步骤:

1.创建 selector, 管理多个 channel

Selector selector = Selector.open();

2.创建ServerSocketChannel

ServerSocketChannel ssc = ServerSocketChannel.open();

3.建立 selector 和 channel 的联系(注册),SelectionKey 就是将来事件发生后,通过它可以知道事件和哪个channel的事件

SelectionKey sscKey = ssc.register(selector, 0, null);

4.关注 accept 事件

sscKey.interestOps(SelectionKey.OP_ACCEPT);

5.绑定端口

ssc.bind(new InetSocketAddress(8080));

Netty是一个基于Java NIO的网络编程框架

分析上面nio中的启动的相关代码,在netty哪些位置会出现,做了什么事,以及netty的启动流程。

Netty的启动代码:
public class TestSourceServer {
    public static void main(String[] args) {
        new ServerBootstrap()
                .group(new NioEventLoopGroup())
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) {
                        ch.pipeline().addLast(new LoggingHandler());
                    }
                }).bind(8080);
    }
}

Netty启动代码的初始化对象流程图:

画板

ServerBootstrap类的依赖关系图:

源码分析:
1.创建selector

group(new NioEventLoopGroup()),在new NioEventLoopGroup()会进行selector的创建,跟nio中的第一步创建selector是一致了。具体可以参考NioEventLoop解析章节

2.doBind

入口 io.netty.bootstrap.ServerBootstrap#bind

关键代码 io.netty.bootstrap.AbstractBootstrap#doBind

private ChannelFuture doBind(final SocketAddress localAddress) {
    // 1. 执行初始化和注册 regFuture 会由 initAndRegister 设置其是否完成,这里是一个异步的过程,从而回调 3.2 处代码
    final ChannelFuture regFuture = initAndRegister();
    final Channel channel = regFuture.channel();
    if (regFuture.cause() != null) {
        return regFuture;
    }
    
    // 2. 因为是 initAndRegister 异步执行,需要分两种情况来看,调试时也需要通过 suspend 断点类型加以区分
    // 2.1 如果已经完成
    if (regFuture.isDone()) {
        ChannelPromise promise = channel.newPromise();
        // 3.1 立刻调用 doBind0
        doBind0(regFuture, channel, localAddress, promise);
        return promise;
    } else {
        // 2.2 还没有完成
        final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
        // 3.2 添加回调操作,回调 执行doBind0
        regFuture.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                Throwable cause = future.cause();
                if (cause != null) {
                    // Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an
                    // IllegalStateException once we try to access the EventLoop of the Channel.
                    promise.setFailure(cause);
                } else {
                    promise.registered();

                    // 3. 由注册线程去执行 doBind0
                    doBind0(regFuture, channel, localAddress, promise);
                }
            }
        });
        return promise;
    }
}
2.1.initAndRegister

接着我们看initAndRegister();方法,关键代码io.netty.bootstrap.AbstractBootstrap#initAndRegister

public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {

  private volatile ChannelFactory<? extends C> channelFactory;

  public B channel(Class<? extends C> channelClass) {
      return channelFactory(new ReflectiveChannelFactory<C>(
          ObjectUtil.checkNotNull(channelClass, "channelClass")
      ));
  }

  final ChannelFuture initAndRegister() {
      Channel channel = null;
      try {
          // 1.来自于ServerBootstrap启动的channel(NioServerSocketChannel.class)方法,通过反射创建NioServerSocketChannel对象
          channel = channelFactory.newChannel();
          // 1.1 初始化 - 做的事就是给NioServerSocketChannel添加一个初始化器 ChannelInitializer
          init(channel);
      } catch (Throwable t) {
          if (channel != null) {
              channel.unsafe().closeForcibly();
              return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
          }
          return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
      }
      // 1.2 注册 - 做的事就是将原生 channel(NioServerSocketChannel) 注册到 selector 上
      ChannelFuture regFuture = config().group().register(channel);
      if (regFuture.cause() != null) {
          if (channel.isRegistered()) {
              channel.close();
          } else {
              channel.unsafe().closeForcibly();
          }
      }
  
      return regFuture;
  }
  
}
2.1.1.channelFactory.newChannel

channelFactory.newChannel()方法,关键代码 io.netty.channel.ReflectiveChannelFactory#newChannel

public class ReflectiveChannelFactory<T extends Channel> implements ChannelFactory<T> {

    private final Constructor<? extends T> constructor;
    
    public T newChannel() {
        try {
            // 调用NioServerSocketChannel的无参构造方法
            return constructor.newInstance();
        } catch (Throwable t) {
            throw new ChannelException("Unable to create Channel from class " + constructor.getDeclaringClass(), t);
        }
    }
    
}

NioServerSocketChannel类,关键代码 io.netty.channel.socket.nio.NioServerSocketChannel#NioServerSocketChannel

public class NioServerSocketChannel extends AbstractNioMessageChannel
                             implements io.netty.channel.socket.ServerSocketChannel {

   private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();

   private static ServerSocketChannel newSocket(SelectorProvider provider) {
        try {
            return provider.openServerSocketChannel();
        } catch (IOException e) {
            throw new ChannelException(
                    "Failed to open a server socket.", e);
        }
    }

    public NioServerSocketChannel() {
        this(newSocket(DEFAULT_SELECTOR_PROVIDER));
    }

    public NioServerSocketChannel(ServerSocketChannel channel) {
        //	会调用父类AbstractChannel将pipeline赋值初始化一个DefaultChannelPipeline对象,以及其他对象的初始化
        super(null, channel, SelectionKey.OP_ACCEPT);
        config = new NioServerSocketChannelConfig(this, javaChannel().socket());
    }
    
}

在newSocket的方法中就是跟nio中的第二步创建ServerSocketChannel是一致了。

2.1.2.init(channel)

关键代码 io.netty.bootstrap.ServerBootstrap#init

@Override
// 这里 channel 实际上是 NioServerSocketChannel
void init(Channel channel) throws Exception {
    final Map<ChannelOption<?>, Object> options = options0();
    synchronized (options) {
        setChannelOptions(channel, options, logger);
    }

    final Map<AttributeKey<?>, Object> attrs = attrs0();
    synchronized (attrs) {
        for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {
            @SuppressWarnings("unchecked")
            AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
            channel.attr(key).set(e.getValue());
        }
    }

    // 得到NioServerSocketChannel的pipeline,也就是默认的DefaultChannelPipeline对象
    ChannelPipeline p = channel.pipeline();

    final EventLoopGroup currentChildGroup = childGroup;
    final ChannelHandler currentChildHandler = childHandler;
    final Entry<ChannelOption<?>, Object>[] currentChildOptions;
    final Entry<AttributeKey<?>, Object>[] currentChildAttrs;
    synchronized (childOptions) {
        currentChildOptions = childOptions.entrySet().toArray(newOptionArray(0));
    }
    synchronized (childAttrs) {
        currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(0));
    }

    // 为 NioServerSocketChannel 添加初始化器
    p.addLast(new ChannelInitializer<Channel>() {
        // 什么时候会被执行呢?
        // 会在注册(io.netty.channel.AbstractChannel.AbstractUnsafe#register0)代码中的pipeline.invokeHandlerAddedIfNeeded()调用到这
        @Override
        public void initChannel(final Channel ch) throws Exception {
            final ChannelPipeline pipeline = ch.pipeline();
            ChannelHandler handler = config.handler();
            if (handler != null) {
                pipeline.addLast(handler);
            }

            // 初始化器的职责是将 ServerBootstrapAcceptor 加入至 NioServerSocketChannel
            ch.eventLoop().execute(new Runnable() {
                @Override
                public void run() {
                    // channelpipline中加入一个ServerBootstrapAcceptor,他其实也是一个入站处理器
                    pipeline.addLast(new ServerBootstrapAcceptor(
                            ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                }
            });
        }
    });
}
2.1.3config().group().register(channel)

描述:将初始化好的channel与创建好的EventLoop关联起来,就是让EventLoop的线程run起来,一直监听 这个channel

config().group()中得到的是NioEventLoopGroup,因为在我们启动的时候使用的是.group(new NioEventLoopGroup())方法。

NioEventLoopGroup类的依赖图:

通过调用MultithreadEventLoopGroup类的register方法最终会调用到SingleThreadEventLoop的register方法中。

关键代码 io.netty.channel.SingleThreadEventLoop#register(io.netty.channel.ChannelPromise)

promise.channel()的对象就是在1.1.2的init方法中传递过来的NioServerSocketChannel对象。NioServerSocketChannel的依赖关系图:

在1.1.2的init方法中的NioServerSocketChannel对象创建过程中会赋值一些属性,

这其中就包括在AbstractChannel#AbstractChannel(io.netty.channel.Channel)中给unsafe创建一个AbstractNioMessageChannel.NioMessageUnsafe的内部类对象,因为newUnsafe()是一个抽象方法,所以会找子类(NioServerSocketChannel)的实现过的方法,而NioServerSocketChannel没有这个newUnsafe方法,所以会找父类AbstractNioMessageChannel的newUnsafe方法创建AbstractNioMessageChannel的内部类对象NioMessageUnsafe。

public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
    
    //省略一些属性
    
    private final Unsafe unsafe;
  
    /**
     * Creates a new instance.
     *
     * @param parent
     *        the parent of this channel. {@code null} if there's no parent.
     */
    protected AbstractChannel(Channel parent) {
        this.parent = parent;
        id = newId();
        unsafe = newUnsafe();
        pipeline = newChannelPipeline();
    }

    protected abstract AbstractUnsafe newUnsafe();
    
}
public abstract class AbstractNioMessageChannel extends AbstractNioChannel {

    /**
     * @see AbstractNioChannel#AbstractNioChannel(Channel, SelectableChannel, int)
     */
    protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
        super(parent, ch, readInterestOp);
    }

    @Override
    protected AbstractNioUnsafe newUnsafe() {
        return new NioMessageUnsafe();
    }

    private final class NioMessageUnsafe extends AbstractNioUnsafe {}
}

promise.channel().unsafe()对象找到父类io.netty.channel.AbstractChannel.AbstractUnsafe中的register方法

关键代码 io.netty.channel.AbstractChannel.AbstractUnsafe#register

调用register0方法时会调用nioEventLoopGroup线程来执行后续的代码

public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {

  protected abstract class AbstractUnsafe implements Unsafe {
    @Override
    public final void register(EventLoop eventLoop, final ChannelPromise promise) {
        if (eventLoop == null) {
            throw new NullPointerException("eventLoop");
        }
        if (isRegistered()) {
            promise.setFailure(new IllegalStateException("registered to an event loop already"));
            return;
        }
        if (!isCompatible(eventLoop)) {
            promise.setFailure(
                    new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));
            return;
        }
    
        AbstractChannel.this.eventLoop = eventLoop;
    
        if (eventLoop.inEventLoop()) {
            register0(promise);
        } else {
            try {
                // 将任务提交给eventLoop
                // 首次执行 execute 方法时,会启动 nioEventLoop 线程,之后注册等操作在 nioEventLoop 线程上执行
                // 因为只有一个 NioServerSocketChannel 因此,也只会有一个 boss nioEventLoop 线程
                // 这行代码完成的事实是 main -> nioEventLoop boss 线程的切换
                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);
            }
        }
    }
    
    private void register0(ChannelPromise promise) {
        try {
            if (!promise.setUncancellable() || !ensureOpen(promise)) {
                return;
            }
            boolean firstRegistration = neverRegistered;
            // 1.2.1 原生的 nio channel 绑定到 selector 上,注意此时没有注册 selector 关注事件,附件为 NioServerSocketChannel
            doRegister();
            neverRegistered = false;
            registered = true;
    
            // 1.2.2 执行 NioServerSocketChannel 初始化器的 initChannel
            pipeline.invokeHandlerAddedIfNeeded();
    
            // 回调 3.2 io.netty.bootstrap.AbstractBootstrap#doBind0
            safeSetSuccess(promise);
            pipeline.fireChannelRegistered();
    
            // 对应 server socket channel 还未绑定,isActive 为 false
            if (isActive()) {
                if (firstRegistration) {
                    pipeline.fireChannelActive();
                } else if (config().isAutoRead()) {
                    // 关注read事件
                    beginRead();
                }
            }
        } catch (Throwable t) {
            closeForcibly();
            closeFuture.setClosed();
            safeSetFailure(promise, t);
        }
    }
  }
  
}

接着执行execute方法,在NioEventLoop中是没有这个方法的,所以向上找(SingleThreadEventExecutor)

@Override
    public void execute(Runnable task) {
        if (task == null) {
            throw new NullPointerException("task");
        }

        boolean inEventLoop = inEventLoop();
        if (inEventLoop) {
            addTask(task);
        } else {
            // 开启线程
            startThread(); 
            // 添加传过来的task到task队列中,注意这里的task中是要执行一个register0(promise)方法的
            addTask(task);
            if (isShutdown() && removeTask(task)) {
                reject();
            }
        }

        if (!addTaskWakesUp && wakesUpForTask(task)) {
            wakeup(inEventLoop);
        }
    }

执行doStartThread()方法:

private void doStartThread() {
        assert thread == null;
        executor.execute(new Runnable() {
            @Override
            public void run() {
                thread = Thread.currentThread();
                if (interrupted) {
                    thread.interrupt();
                }

                boolean success = false;
                updateLastExecutionTime();
                try {
                    // 开始线程
                    SingleThreadEventExecutor.this.run(); 
                    success = true;
                } catch (Throwable t) {
                    logger.warn("Unexpected exception from an event executor: ", t);
                } finally {
                    for (;;) {
                        int oldState = STATE_UPDATER.get(SingleThreadEventExecutor.this);
                        if (oldState >= ST_SHUTTING_DOWN || STATE_UPDATER.compareAndSet(
                                SingleThreadEventExecutor.this, oldState, ST_SHUTTING_DOWN)) {
                            break;
                        }
                    }

                    // Check if confirmShutdown() was called at the end of the loop.
                    if (success && gracefulShutdownStartTime == 0) {
                        logger.error("Buggy " + EventExecutor.class.getSimpleName() + " implementation; " +
                                SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must be called " +
                                "before run() implementation terminates.");
                    }

                    try {
                        // Run all remaining tasks and shutdown hooks.
                        for (;;) {
                            if (confirmShutdown()) {
                                break;
                            }
                        }
                    } finally {
                        try {
                            cleanup();
                        } finally {
                            STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
                            threadLock.release();
                            if (!taskQueue.isEmpty()) {
                                logger.warn(
                                        "An event executor terminated with " +
                                                "non-empty task queue (" + taskQueue.size() + ')');
                            }

                            terminationFuture.setSuccess(null);
                        }
                    }
                }
            }
        });
    }

进入SingleThreadEventExecutor.this.run()方法:

在这里会死循环,监听selector上的事件或者是任务

@Override
    protected void run() {
        // 死循环,监听selector上的事件或者是任务
        for (;;) {
            try {
                switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
                    case SelectStrategy.CONTINUE:
                        continue;
                    case SelectStrategy.SELECT:
                        select(wakenUp.getAndSet(false));
                        if (wakenUp.get()) {
                            selector.wakeup();
                        }
                    default:
                        // fallthrough
                }

                cancelledKeys = 0;
                needsToSelectAgain = false;
                final int ioRatio = this.ioRatio;
                if (ioRatio == 100) {
                    try {
                        processSelectedKeys();
                    } finally {
                        // Ensure we always run tasks.
                        runAllTasks();
                    }
                } else {
                    final long ioStartTime = System.nanoTime();
                    try {
                        processSelectedKeys();
                    } finally {
                        // register0(channel);是一个普通任务,所以会在这执行
                        final long ioTime = System.nanoTime() - ioStartTime;
                        // 这里会回调上面提到的提交的task,也就是register0(channel);
                        runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
                    }
                }
            } catch (Throwable t) {
                handleLoopException(t);
            }
            // Always handle shutdown even if the loop processing threw an exception.
            try {
                if (isShuttingDown()) {
                    closeAll();
                    if (confirmShutdown()) {
                        return;
                    }
                }
            } catch (Throwable t) {
                handleLoopException(t);
            }
        }
    }

调用内部类(AbstractUnsafe)的外部类(AbstractChannel)的doRegister()方法,有一个this$0的指针指向外部对象

关键代码 io.netty.channel.AbstractChannel#doRegister

doRegister并没有任何的注册实现,由子类来重写doRegister实现注册,而当前的this$0的指针指向外部对象是NioServerSocketCahnnel对象,NioServerSocketCahnnel对象的父类AbstractNioChannel中有doRegister方法。

protected void doRegister() throws Exception {
    // NOOP
}

关键代码 io.netty.channel.nio.AbstractNioChannel#doRegister

@Override
protected void doRegister() throws Exception {
    boolean selected = false;
    for (;;) {
        try {
            // 建立 selector 和 channel 的联系(注册)
            selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 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;
            }
        }
    }
}

这里可以看到ServerSocketChannel注册到NioEventLoop的选择器上,并同时将this(NioServerSocketChannel)对象作为附件保存下来。

跟nio中的第三步建立 selector 和 channel 的联系是一致了。

关键代码 io.netty.channel.ChannelInitializer#initChannel

private boolean initChannel(ChannelHandlerContext ctx) throws Exception {
    if (initMap.add(ctx)) { // Guard against re-entrance.
        try {
            // 1.2.2.1 执行初始化
            initChannel((C) ctx.channel());
        } catch (Throwable cause) {
            exceptionCaught(ctx, cause);
        } finally {
            // 1.2.2.2 移除初始化器
            ChannelPipeline pipeline = ctx.pipeline();
            if (pipeline.context(this) != null) {
                pipeline.remove(this);
            }
        }
        return true;
    }
    return false;
}
2.2.doBind0(regFuture, channel, localAddress, promise);

执行doBind0是在另一个线程nioEventLoopGroup中执行

关键代码 io.netty.bootstrap.AbstractBootstrap#doBind0

// 由1.doBind源码分析的3.1 或 3.2 执行 doBind0,这里的channel是NioServerSocketChannel
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() {
            // initAndRegister是否成功
            if (regFuture.isSuccess()) {
                channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
            } else {
                promise.setFailure(regFuture.cause());
            }
        }
    });
}

关键代码io.netty.channel.AbstractChannel.AbstractUnsafe#bind

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

    if (!promise.setUncancellable() || !ensureOpen(promise)) {
        return;
    }

    if (Boolean.TRUE.equals(config().getOption(ChannelOption.SO_BROADCAST)) &&
        localAddress instanceof InetSocketAddress &&
        !((InetSocketAddress) localAddress).getAddress().isAnyLocalAddress() &&
        !PlatformDependent.isWindows() && !PlatformDependent.maybeSuperUser()) {
        // 记录日志...
    }

    boolean wasActive = isActive();
    try {
        // 3.3 执行端口绑定
        doBind(localAddress);
    } catch (Throwable t) {
        safeSetFailure(promise, t);
        closeIfClosed();
        return;
    }

    if (!wasActive && isActive()) {
        invokeLater(new Runnable() {
            @Override
            public void run() {
                // 3.4 触发 active 事件
                pipeline.fireChannelActive();
            }
        });
    }

    safeSetSuccess(promise);
}

关键代码 io.netty.channel.socket.nio.NioServerSocketChannel#doBind

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

跟nio中的第五步绑定端口是一致了。

接着执行3.4 触发 active 事件:

关键代码 io.netty.channel.DefaultChannelPipeline.HeadContext#channelActive

public void channelActive(ChannelHandlerContext ctx) {
    ctx.fireChannelActive();
	// 触发 read (NioServerSocketChannel 上的 read 不是读取数据,只是为了触发 channel 的事件注册)
    readIfIsAutoRead();
}

关键代码io.netty.channel.nio.AbstractNioChannel#doBeginRead

protected void doBeginRead() 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();
    // readInterestOp 取值是 16,在 NioServerSocketChannel 创建时初始化好,代表关注 accept 事件
    if ((interestOps & readInterestOp) == 0) {
        selectionKey.interestOps(interestOps | readInterestOp);
    }
}

跟nio中的第四步关注 accept 事件是一致了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值