netty源码之Channel:注重NioServerSockerChannel和NioSocketChannel

类结构展示

1、NioServerSockerChannel的类结构:

在这里插入图片描述

2、NioSocketChannel的类结构:

在这里插入图片描述

顶层接口Channel

在这里插入图片描述
Channel接口中还包含了另一个顶层接口Unsafe,其实这个Unsafe才是承受了最多的脏活累活的家伙。
id()方法返回Channel实例的id。
eventLoop()方法返回给Channel实例关联的EventLoop实例。
parent()方法返回该Channel的父Channel,服务端才有。
unsafe()方法返回该Channel使用的Unsafe实例。
pipeline()方法返回该Channel关联的ChannelPipeline实例。
alloc()方法返回该Channel的内存分配器ByteBufAllocator实例。
read()和flush()是两个出站方法,会调用pipeline的出站方法。

骨架类AbstractChannel

1、属性

在这里插入图片描述
定义了netty网络通信的基本属性。

2、构造方法

在这里插入图片描述

id是netty提供了一个实现算法。
unsafe是一个钩子方法,执行时调用子类实现方法。
pipeline是new了一个DefaultChannelPipeline。注意,这里实例化DefaultChannelPipeline的时候就会创建HeadContext和TailContext。

3、实现方法

在这里插入图片描述
实现了诸如上面的一些网络通信方法,但是只是单纯调用了pipeline的对应方法。
此外,还定义了一批抽象方法,让子类去具体实现。
在这里插入图片描述

NIO骨架类AbstractNioChannel

1、新增的属性

在这里插入图片描述
新增了网络通信中NIO模式使用的对象,selector用到的一些东西。
SelectableChannel,这个玩意是java提供的,代码中看到的javaChannel()方法返回的就是这个玩意,类比于NIO编程中的ServerSocketChannel和SocketChannel。

2、构造方法

在这里插入图片描述
调用父类实例化unsafe和pipline。
赋值SelectableChannel,构造方法传入。
赋值感兴趣的操作readInterestOp,构造方法传入。
设置SelectableChannel为非阻塞模式,类比于NIO设置ServerSockerChannle启动时设置非阻塞模式。

3、实例方法

doRegister()方法

在这里插入图片描述
做的事情也很简单,将channel注册到selector上,但是注册的事件是一个0,以为着不关注任何事件。

doBeginRead()方法

在这里插入图片描述
检查当前channel的selectionKey,并将构造函数传进来的readInterestOp事件类型添加到其中,表示该channel开始关注readInterestOp事件。

AbstractNioMessageChannel

1、newUnsafe()

在这里插入图片描述
负责自己及其子类的unsafe实例化。NioMessageUnsafe的实例。

2、doWrite(ChannelOutboundBuffer in)方法

在这里插入图片描述
在一个死循环中进行写操作,具体的操作在一个抽象方法中,由具体的子类实现,如果发现ChannelOutboundBuffer中的内容已经全部写完,则取消对写事件的关注。如果在写数据的时候发现缓冲区满了写不进去,就继续关注写事件。

AbstractNioByteChannel

1、newUnsafe()方法

在这里插入图片描述负责自己及其子类的unsafe实例化。NioByteUnsafe的实例。

2、doWrite(ChannelOutboundBuffer in)方法

在这里插入图片描述
首先获取一次性默认写次数限制writeSpinCount,默认值是16,表示该线程在这次写任务中最多写16次,到了16次还没有写完的化,也会释放线程的控制权,将剩余的写需求封装成任务入队列。这样设计的目的是防止有大文件的操作一直占用io线程。

如果已经写完了,取消关注写事件。

调用doWriteInternal()方法去执行写操作,正常情况会返回1。

最后判断writeSpinCount与0的大小关系进行incompleteWrite()处理。

3、clearOpWrite()方法

在这里插入图片描述
很easy.

4、doWriteInternal(ChannelOutboundBuffer in, Object msg)

在这里插入图片描述
对ByteBuf和文件类型是两种处理方法,但是具体的写操作还是放在了子类中实现。

5、incompleteWrite(boolean setOpWrite)方法

在这里插入图片描述
分别对没有写完消息的两种情况作了处理。
如果是因为缓冲区满了,就注册关注写事件,代写缓冲区有空间了继续写。
如果是因为写了16次还没有写完,就生成任务放进线程队列后续继续写。

NioServerSocketChannel

1、构造方法

在这里插入图片描述

private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER 
	= SelectorProvider.provider();

在这里插入图片描述
调用JDK NIO的方法返回一个SelectorProvider,这个东西跟操作系统有关,有WindowsSelectorProvider和LinuxSelectorProvider。
在这里插入图片描述
返回一个JDK的ServerSockerChannel。
在这里插入图片描述
调用父类的构造方法,注意参数SelectionKey.OP_ACCEPT,它会传递给AbstractNioChannel类将readInterestOp属性赋值,并在其doBeginRead()方法时注册该事件,表示该channel关注接收连接事件。

2、doBind(SocketAddress localAddress)方法

在这里插入图片描述
调用JDK channel的绑定方法进行绑定。

3、doReadMessages(List buf)方法

该方法是NioServerSocketChannel的重点,表示接收连接行为。
在这里插入图片描述
在这里插入图片描述

NioSocketChannel

1、构造方法

在这里插入图片描述
在这里插入图片描述

2、doBind(SocketAddress localAddress)方法

在这里插入图片描述
一样是调用JDK的底层方法。

3、doConnect(SocketAddress remoteAddress, SocketAddress localAddress)方法

在这里插入图片描述
调用底层方法进行连接,因为行为是异步的,如果没有直接连接的话,会给channel注册关注连接事件。

4、doWrite(ChannelOutboundBuffer in)方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述