Netty源码之客户端连接监听和客户端channel创建 服务端视角

在前两篇博客中,我们讲解了服务端的启动和EventLoop相关的源码,接下来,我们看一下服务端是如何监听客户端接入并建立连接的: private void processSelectedKey(SelectionKey k, AbstractNioChannel ch)当客户端想和服务端建立连接的时候,会被服务端channel绑定的selector轮询到这个io事件,之后就会调用上面这个方法...
摘要由CSDN通过智能技术生成

在前两篇博客中,我们讲解了服务端的启动和EventLoop相关的源码,接下来,我们看一下服务端是如何监听客户端接入并建立连接的:

 private void processSelectedKey(SelectionKey k, AbstractNioChannel ch)

当客户端想和服务端建立连接的时候,会被服务端channel绑定的selector轮询到这个io事件,之后就会调用上面这个方法来处理这个io事件,接下来我们就在这个地方开始展开:

//获得服务端channel的unsafe类
final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();
//验证key的有效性
        if (!k.isValid()) {
            final EventLoop eventLoop;
            try {
                eventLoop = ch.eventLoop();
            } catch (Throwable ignored) {
               
                return;
            }
            if (eventLoop != this || eventLoop == null) {
                return;
            }
            unsafe.close(unsafe.voidPromise());
            return;
        }

一开始需要获得unsafe类,毕竟那些io事件都是通过它来处理的,接着就要验证attachment的有效性:

int readyOps = k.readyOps();
if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
                unsafe.read();
                if (!ch.isOpen()) {
                    // Connection already closed - no need to handle write.
                    return;
                }
            }

之后就会获得当前attachment注册的感兴趣的事件,对于服务端channel就是accept事件,所以最终会进入这个分支,之后就会调用unsafe类的read方法,在这不要把read方法混淆,由于服务端的channel是专门用来处理客户端连接的,所以它内部创建的unsafe类也是专门处理连接的,进去看一下read方法:

public void read() {
            assert eventLoop().inEventLoop();
            //获得当前channel的配置
            final ChannelConfig config = config();
            //获得当前channel的pipeline
            final ChannelPipeline pipeline = pipeline();
            //分配一个新的接收缓冲区,该缓冲区的容量可能大到足以读取所有入站数据,也足够小不要浪费空间。
            final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
            allocHandle.reset(config);

            boolean closed = false;
            Throwable exception = null;
            try {
                try {
               		 //在这里面是来循环读取请求的连接,先存储到readBuf中
                    do {
                        int localRead = doReadMessages(readBuf);
                        if (localRead == 0) {
                            break;
                        }
                        if (loca
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值