1.Netty之NioServerSocketChannel运行之道

服务端启动过程中并没有相关的IO事件,即事件调度层在此期间处理均为普通任务队列中的任务。

ServerBootstrap存在两个属性:childHandler & handler。childHandler为 NioSocketChannel 的pipeline编排ChannelHandler,后者是为NioServerSocketChannel的pipeline编排ChannelHandler。

NioServerSocketChannel整个生命周期只是关注Accept事件,所以针对NioServerSocketChannel通过 handler方法 为其自定义各种类型的ChannelHandler没有任何意义。

1.bind事件 & channelActive & Accept事件的关注

public abstract class AbstractBootstrap{

    private ChannelFuture doBind(final SocketAddress localAddress) {
        ChannelFuture regFuture = initAndRegister();
        ...
        if (regFuture.isDone()) {
            ...
        } else {
            PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
            regFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) {
                    doBind0(regFuture, channel, localAddress, promise);
                }
            });
            return promise;
        }
    }
}
public abstract class AbstractChannel{
    protected abstract class AbstractUnsafe implements Unsafe {
        public final void bind(final SocketAddress localAddress, final ChannelPromise promise) {
            ...
            //端口绑定之前Channel尚处未激活状态
            boolean wasActive = isActive();
            //NioServerSocketChannel内部真正绑定端口:javaChannel().bind(localAddress, config.getBacklog());
            doBind(localAddress);
            //端口绑定之后Channel处于激活状态
            if (!wasActive && isActive()) {
                invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        // interestOps 为Accept事件
                        pipeline.fireChannelActive();
                    }
                });
            }
            safeSetSuccess(promise);
        }
    }
}

如上伪代码所示:NioServerSocketChannel完成端口绑定之后,在 NioServerSocketChannel 通过 fireChannelActive流转每个ChannelHandler过程中顺便为其SelectionKey设置感兴趣事件【interestOps】为Accept事件

2.ServerBootstrapAcceptor

客户端NioSocketChannel发起connect事件后,服务端事件调度层轮询过程中监听到NioServerSocketChannel对应的SelectionKey存在IO事件,即Accept事件。

public abstract class AbstractNioMessageChannel extends AbstractNioChannel {
    
    private final class NioMessageUnsafe extends AbstractNioUnsafe {

        // 字段 readBuf集合其元素类型即为 NioSocketChannel
        private final List<Object> readBuf = new ArrayList<Object>();
        @Override
        public void read() {
            assert eventLoop().inEventLoop();
            final ChannelConfig config = config();
            // 从 NioServerSocketChannel 得到其 ChannelPipeline
            final ChannelPipeline pipeline = pipeline();
            final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
            allocHandle.reset(config);
            boolean closed = false;
            Throwable exception = null;
            do {
                // 从 NioServerSocketChannel accept客户端连接对象 NioSocketChannel
                int localRead = doReadMessages(readBuf);
                ...
                allocHandle.incMessagesRead(localRead);
            } while (allocHandle.continueReading());
            int size = readBuf.size();
            for (int i = 0; i < size; i ++) {
                readPending = false;
                // 执行 ChannelPipeline 维护的 channelHandler责任链
                pipeline.fireChannelRead(readBuf.get(i));
            }
            pipeline.fireChannelReadComplete();
            ...
        }
    }
}

如上伪代码所示:NioServerSocketChannel所属的pipeline携带NioSocketChannel执行所有handler之channelRead方法。其中最为重要的就属handler之ServerBootstrapAcceptor。

public class ServerBootstrap{
    private static class ServerBootstrapAcceptor extends ChannelInboundHandlerAdapter {
        private final EventLoopGroup childGroup;
        private final ChannelHandler childHandler;
        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            Channel child = (Channel) msg;//此时child即为NioSocketChannel
            // 为 NioSocketChannel的pipeline编排handler
            child.pipeline().addLast(childHandler);
            // 线程切换
            childGroup.register(child).addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (!future.isSuccess()) {
                        forceClose(child, future.cause());
                    }
                }
            });
        }
    }   
}

如上伪代码所示:线程切换是指bossGroup -> workGroup。从 workGroup 选择某个NioEventLoop为当前 NioSocketChannel 开启事件调度层。

后续流程即为 NioSocketChannel 的注册流程,主要即为当前channel对应的SelectionKey设置感兴趣事件【interestOps】为Read事件,正常与客户端数据交互~

至此 bossGroup 已经完成一次Accept事件的使命,继续轮回~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值