这个分享阅读的是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接口的抽象实现,它主要维护了EventLoop和ChannelPipeline等属性,已经将ChannelOutboundInvoker的方法委托给ChannelPipeline来进入从TailContext到HeadContext的调用链中。
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。