Netty中主reactor在接收到连接请求时处理分析

NioEventLoop在processSelectedKey时,当有连接到来时,会调用下面

if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
	unsafe.read();
}

调用AbstractNioMessageChannel.NioMessageUnsafe#read来读取数据

public void read() {
	assert eventLoop().inEventLoop();
	final ChannelConfig config = config();
	final ChannelPipeline pipeline = pipeline();
	final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
	allocHandle.reset(config);

	boolean closed = false;
	Throwable exception = null;
	try {
		try {
			do {
				int localRead = doReadMessages(readBuf);
				if (localRead == 0) {
					break;
				}
				if (localRead < 0) {
					closed = true;
					break;
				}

				allocHandle.incMessagesRead(localRead);
			} while (continueReading(allocHandle));
		} catch (Throwable t) {
			exception = t;
		}

		int size = readBuf.size();
		for (int i = 0; i < size; i ++) {
			readPending = false;
			pipeline.fireChannelRead(readBuf.get(i));
		}
		readBuf.clear();
		allocHandle.readComplete();
		pipeline.fireChannelReadComplete();

		if (exception != null) {
			closed = closeOnReadError(exception);

			pipeline.fireExceptionCaught(exception);
		}

		if (closed) {
			inputShutdown = true;
			if (isOpen()) {
				close(voidPromise());
			}
		}
	} finally {
		// Check if there is a readPending which was not processed yet.
		// This could be for two reasons:
		// * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method
		// * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method
		//
		// See https://github.com/netty/netty/issues/2254
		if (!readPending && !config.isAutoRead()) {
			removeReadOp();
		}
	}
}

当中有调用doReadMessages来读取数据,调用的是NioServerSocketChannel#doReadMessages

    protected int doReadMessages(List<Object> buf) throws Exception {
        SocketChannel ch = SocketUtils.accept(javaChannel());

        try {
            if (ch != null) {
                buf.add(new NioSocketChannel(this, ch));
                return 1;
            }
        } catch (Throwable t) {
            logger.warn("Failed to create a new channel from an accepted socket.", t);

            try {
                ch.close();
            } catch (Throwable t2) {
                logger.warn("Failed to close a socket.", t2);
            }
        }

        return 0;
    }

创建NioSocketChannel添加到buf列表中。读完后,触发Pipeline的fireChannelRead,会触发ServerBootstrapAcceptor#channelRead,ServerBootstrapAcceptor这个Handler是在NioServerSocketChannel注册到BossGroup中时添加的。ServerBootstrapAcceptor#channelRead定义如下

public void channelRead(ChannelHandlerContext ctx, Object msg) {
	final Channel child = (Channel) msg;

	child.pipeline().addLast(childHandler);

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

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

参数中的msg就是NioSocketChannel,将其注册到ChildGroup中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值