上一节学习客户端channel的创建过程。至此,客户端和服务端的创建过程我们都学习了一般。
本节总结一下channel的分类。经过简化后得如下UML
- 顶层
Channel
接口定义了socket事件如读、写、连接、绑定等事件,并使用AbstractChannel
作为骨架实现了这些方法。查看器成员变量,发现大多数通用的组件,都被定义在这里,比如:parent,id,unsafe,pipeline,eventLoop
等之前学习分析源码的时候都见到过。
private final Channel parent;
private final ChannelId id;
private final Unsafe unsafe;
private final DefaultChannelPipeline pipeline;
private final VoidChannelPromise unsafeVoidPromise = new VoidChannelPromise(this, false);
private final CloseFuture closeFuture = new CloseFuture(this);
private volatile SocketAddress localAddress;
private volatile SocketAddress remoteAddress;
private volatile EventLoop eventLoop;
private volatile boolean registered;
private boolean closeInitiated;
/** Cache for the string representation of this channel */
private boolean strValActive;
private String strVal;
- 第二层
AbstractNioChannel
定义了以NIO,即Selector的方式进行读写事件的监听。
其成员变量保存了selector相关的一些属性。
private final SelectableChannel ch;
protected final int readInterestOp;
volatile SelectionKey selectionKey;
boolean readPending;
- 第三层内容比较多,定义了服务端channel(左边继承了
AbstractNioMessageChannel
的NioServerSocketChannel
)以及客户端channel(右边继承了AbstractNioByteChannel
的NioSocketChannel
)。
- 回忆分别创建客户端和服务端的过程,它们都想父类注册了读事件,但是其含义并非以言个,对于客户端来书,读指的是IO读写。而对于服务端来说读指的是检测新连接接入。
protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) {
//传入感兴趣的读事件:客户端channel的读事件
super(parent, ch, SelectionKey.OP_READ);
}
public NioServerSocketChannel(ServerSocketChannel channel) {
//传入感兴趣的读事件:服务端channel的读事件(accept)
super(null, channel, SelectionKey.OP_ACCEPT);
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
-
对于实际上不同的读实现。则交给了分别的内部类
NioMessageUnsafe
和NioByteUnsafe
来实现。因此服务端和客户但分别持有的unsalf
则是这两个类的实例,实现了具体的读写协议。 -
服务端
NioServerSocketChannel
和客户端NioSocketChannel
都持有config
,分别是:NioServerSocketChannelConfig
和NioSocketChannelConfig
,主要存储每种channel底层的一个配置。对应着channel的架构,config的架构也是有一些公共的配置以及配置的获取和设置被抽象出来,如下图UML所示。
网友评论