Netty接收客户端连接

2022-06-02 13:49:03 浏览数 (1)

昨天的'Netty从0到1的运作流程'文章中我们介绍了Netty如何启动以及如何接收客户端请求, 如果有疑惑可以给我发邮件promiss217@outlook.com或者去我的个人站点https://www.infuq.com/manual/feedback.html提反馈信息.

今天我们主要讲解Netty如何接收客户端请求.

当服务端启动以后, 此时有客户端发送请求过来, 那么服务端接收到此请求, 在服务端处理IO请求的过程.

代码语言:javascript复制
if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
      unsafe.read();
  }

当是ACCEPT请求时, 读取客户端连接.

代码语言:javascript复制
@Override
  protected int doReadMessages(List<Object> buf) throws Exception {
      SocketChannel ch = SocketUtils.accept(javaChannel());
      if (ch != null) {
          buf.add(new NioSocketChannel(this, ch));
          return 1;
      }

      return 0;
  }

读取的JDK-Channel并封装成NioSocketChannel. 在前面的文章我们说过, 此处默认读取16个客户端. 读取之后

代码语言:javascript复制
for (int i = 0; i < size; i   ) {
    pipeline.fireChannelRead(readBuf.get(i));
}

通过for循环依次'传给'Pipeline中. 而在NioServerSocketChannel关联的Pipeline中有个ServerBootstrapAcceptor, 它是一个处理器Handler.

代码语言:javascript复制
public void channelRead(ChannelHandlerContext ctx, Object msg) {
    final Channel child = (Channel) msg;

    child.pipeline().addLast(childHandler);

    setChannelOptions(child, childOptions, logger);
    setAttributes(child, childAttrs);

    childGroup.register(child).addListener(new ChannelFutureListener() {
        @Override
        public void operationComplete(ChannelFuture future) throws Exception {
            if (!future.isSuccess()) {
                forceClose(child, future.cause());
            }
        }
    });
}

这个处理器会向客户端的Channel设置选项和属性.以及添加childHandler.之后会选择一个NioEventLoop, 并将Channel注册到这个NioEventLoop.

但实际的注册是以任务的形式添加到这个NioEventLoop对应的MpscQueue中.注册作为第一个任务, 也表示会启动这个NioEventLoop, 顺理成章会创建一个线程.

注册的过程会触发channelRegistered事件, channelActive事件,最后会向Selector设置READ事件. 至此客户端便可以读写IO操作了.

0 人点赞