===== 服务端 ===== - 初始化NioServerSocketChannel - 初始化NioServerSocketChannel.pipeline。在pipeline中初始化一个 ChannelInitializer任务:任务内容 - 当NioServerSocketChannel注册完成时,为pipeline添加handler(注意不是childHandler) - 当NioServerSocketChannel注册完成时,为pipeline添加ServerBootstrapAcceptor (用于处理接受用户连接) - 当NioServerSocketChannel注册完成后,从pipeline上删除ChannelInitializer任务本身。 - 将NioServerSocketChannel 注册到boss中一个NioEventLoop上,生成NioServerSocketChannel.selectionKey - 绑定ip和端口 - 设置NioServerSocketChannel.selectionKey 的interestOps = 16 (只关注Accept请求) - 相关代码:pipeline.fireChannelActive() - == - 客户端连接过来 - == - 上面ServerBootstrapAcceptor这个handler来处理用户的连接操作 - 初始化NioSocketChannel - 初始化NioSocketChannel.pipeline。增加用户自定义的childHandler - 将NioSocketChannel注册到到work中一个NioEventLoop上 - 置NioSocketChannel.selectionKey 的interestOps = 1 (只关Read请求) - 相关代码:pipeline.fireChannelActive() ===== 客户端 ===== - 初始化NioSocketChannel - 初始化NioSocketChannel.pipeline。增加用户自定义的childHandler - 将NioSocketChannel注册到到work中一个NioEventLoop上 - 连接到远程服务端的ip和端口,等待服务端接收连接 - 客户端设置interestOps = SelectionKey.CONNECT ,开始监听服务端接受连接的消息 - 服务端接受连接,客户端收到SelectionKey.CONNECT消息 - 客户端设置interestOps = SelectionKey.OP_READ, 开始监听服务端发来的数据 ===== 额外的细节 ===== * selector 接收消息,NioSocketChannel中的unsafe处理数据,交给NioSocketChannel.pipeline处理 * 先由HeadContext处理 * 然后是自定义的hander * 最后是TailContext * 中途可以打断handler调用链条,上游的hander不调用ctx.fireChannelRead(msg); 就不会触发下游的hander * handler也可以设置专用线程池去处理 .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); if (sslCtx != null) { p.addLast(sslCtx.newHandler(ch.alloc())); } //p.addLast(new LoggingHandler(LogLevel.INFO)); p.addLast(new EchoServerHandler()); p.addLast(new EventExecutorGroup(),new EchoServerHandler()); // 可以为某个handler设置线程池 } }); {{:pasted:20210730-092825.png}}