netty源码阅读之十(channel概述)

本文详细解析了Netty中Channel的实现原理,包括其作为网络管道的包装类的角色,内部的Unsafe接口,以及Channel与其他核心组件如ChannelPipeline、ChannelHandlerContext的关系。通过分析NioSocketChannel和NioServerSocketChannel的继承树,阐述了Channel在Netty架构中的关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个分享阅读的是4.1.52.Final-SNAPSHOT这个版本的源码 

channel主要是作为网络管道的包装类,对于不同类型的管道进行了抽象,并对它们进行了相应的包装,并对外提供了对应管道的状态,以及相应管道的IO等方法。

Channel内部还提供了一个Unsafe接口,这个接口是用于netty内部对channel进行调用,而不由外部来进行操作。

在具体介绍Channel之前,有不要介绍一下Channel,ChannelPipeline,ChannelHandlerContext,ChannelHandler,EventLoop,Unsafe等之间的关系。

可以看到每个Channel都会维护一个ChannelPipeline对象,以及一个Unsafe对象,其中ChannelPipeLine对象则主要是维护ChannelHandlerContext双向链表,这个双向链表是netty定义的两种类型方法ChannelInboundHandler和ChannelOutBoundHandler的调用链表,其中下图中红色线时ChannelInoundHandler方法的流向,而黑色线则是ChanneleOutboundHandler的流向。

可以看到每个EventLoop可以绑定多个Channel,而EventLoop则主要是负责维护这些channel对应的实际的IO的channel,如SocketChannel等对应的Selector注册器,EventLoop通过注册到这些Selector感知IO事件的产生,从而调用对应的Unsafe的相应的处理方法来进行相应的处理,如read()读取数据,从而会产生Inbound方法,如fireChannelRead,fireChannelReadComplete等。

 还可以看到上面的ChannelPipeline的头必定是HeadContext,尾部必定是TailContext,对于inbound的方法的处理主要是从head到tail,outbound的处理则是从tail到head,下面的表格列出了所有的inbound和outbound方法。以及headContext和TailContext对这两种方法的处理。

可以看到下面表格中对于outbound的方法,是从tail到head的处理链,主要是通过channel调用对应的方法,最后到unsafe结束如bind方法则是channel调用bind方法,然后AbstractChannel的实现则是调用其内部的pipeline的bind方法,然后tail没进行处理,在然后经过从tail到head的所有的outboundHandler对bind方法的处理,最后在head中调用unsafe的bind方法,unsafe在最终调用其内部维护的SocketChannel,ServerSocketChannel等的对应的bind方法来完成绑定。

对于inound方法,可以看到head的处理主要是进行相应的ctx的fire操作,将对应的操作给下一个inboundHandler来处理,不过有几个方法会比较特殊,一个是channelRegistered会在其前面检查是否是第一次register,从而会调用相关的回调,其中主要的事情则是调用callHandlerAdded()这个事件表示handler的加入,另外则是在fireChannelUnregistered的时候则是调用destroy方法,主要是调用callHandlerRemoved()这个事件表示移除,还有则是配置了自动读时则是会调用readIfAutoRead()来自动调用channel的read()方法进行数据读取操作。

NioSocketChannel,NioServerSocketchannel的继承树

对于channel则主要分析常用的nioSocketChannel和NioServerSocketChannel,下面是NioSocketChannel的继承树

可以看到其最上层的类是DefaultAttributeMap,这个类主要是实现了AttributeMap接口,主要是实现了一个类似于HashMap的数组散列,不过其是线程安全的,又没有ConcurrentHashMap<>()实现的那么复杂,因为它主要是进行get和set的操作,所以只是对散列表的头进行锁定,而不需要锁段等操作。

在下面的则是AbstractChannel这个类,可以看到这个类实现了Channel接口,而Channel则实现了ChannelOutboundInvoker接口,AbstractChannel是Channel接口的抽象实现,它主要维护了EventLoopChannelPipeline等属性,已经将ChannelOutboundInvoker的方法委托给ChannelPipeline来进入从TailContextHeadContext的调用链中。

AbstractNioChannel看名字则可以知道其内部的io的操作使用的是nio,它主要是对SelectableChannel,readInterestOp,selectionKey等nio相关的属性。

AbstractNioByteChannel表示其对应的channel操作的是byte

NioSocketChannel主要表示其包装的channel为nio的客户端对应的channel。

下图则是与NioSocketChannel对应的NioSocketChannelUnsafe的继承树,Unsafe中的方法主要是两处来进行调用,一处是HeadContext对outbound的操作最终会调用相关的unsafe方法来进行最后的操作。还有一处则是在NioLoopGroup等loopGroup收到了管道的信息后调用Unsafe中对应的方法来进行对应的处理。

可以看到对于Unsafe的实现最开始是AbstractUnsafe,这个类实现了主要的功能,如register,deregister,disconnect,close,bind,beginRead, write,flush。

而在它下面的AbstractNioUnsafe主要是实现了NioUnsafe接口,它主要是用于NioEventLoop中有对应的IO事件则调用其对应的Unsafe进行操作。

NioByteBuf表示的其管道的数据是ByteBuf,故此对于读取和写入都以字节形式。

最后的NioSocketChannelUnsafe表示的是其对应的Io的channel是NioSocketChannel。

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值