类似于 java.nio 包 的 Channel,Netty 提供了自己的 Channel 和其子类实现,用于异步 I/O 操作 等。Unsafe 是 Channel 的内部接口,聚合在 Channel 中协助进行网络读写相关的操作,因为它的设计初衷就是 Channel 的内部辅助类,不应该被 Netty 框架 的上层使用者调用,所以被命名为 Unsafe。
Channel 组件
Netty 的 Channel 组件 是 Netty 对网络操作的封装,如 网络数据的读写,与客户端建立连接,主动关闭连接 等,也包含了 Netty 框架 相关的一些功能,如 获取该 Chanel 的 EventLoop、ChannelPipeline 等。另外,Netty 并没有直接使用 java.nio 包 的 SocketChannel 和 ServerSocketChannel,而是使用 NioSocketChannel 和 NioServerSocketChannel 对其进行了进一步的封装。下面我们先从 Channel 接口 的 API 开始分析,然后看一下其重要子类的源码实现。
为了便于后面的阅读源码,我们先看下 NioSocketChannel 和 NioServerSocketChannel 的继承关系类图。
Channel 接口
public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel> {
/**
* Channel 需要注册到 EventLoop 的多路复用器上,用于处理 I/O事件,
* EventLoop 实际上就是处理网络读写事件的 Reactor线程。
*/
EventLoop eventLoop();
/**
* ChannelMetadata 封装了 TCP参数配置
*/
ChannelMetadata metadata();
/**
* 对于服务端Channel而言,它的父Channel为空;
* 对于客户端Channel,它的 父Channel 就是创建它的 ServerSocketChannel
*/
Channel parent();
/**
* 每个 Channel 都有一个全局唯一标识
*/
ChannelId id();
/**
* 获取当前 Channel 的配置信息,如 CONNECT_TIMEOUT_MILLIS
*/
ChannelConfig config();
/**
* 当前 Channel 是否已经打开
*/
boolean isOpen();
/**
* 当前 Channel 是否已注册进 EventLoop
*/
boolean isRegistered();
/**
* 当前 Channel 是否已激活
*/
boolean isActive();
/**
* 当前 Channel 的本地绑定地址
*/
SocketAddress localAddress();
/**
* 当前 Channel 的远程绑定地址
*/
SocketAddress remoteAddress();
/**
* 当前 Channel 是否可写
*/
boolean isWritable();
/**
* 当前 Channel 内部的 Unsafe对象
*/
Unsafe unsafe();
/**
* 当前 Channel 持有的 ChannelPipeline
*/
ChannelPipeline pipeline();
/**
* 从当前 Channel 中读取数据到第一个 inbound缓冲区 中,如果数据被成功读取,
* 触发ChannelHandler.channelRead(ChannelHandlerContext,Object)事件。
* 读取操作API调用完成之后,紧接着会触发ChannelHandler.channelReadComplete(ChannelHandlerContext)事件,
* 这样业务的ChannelHandler可以决定是否需要继续读取数据。如果己经有读操作请求被挂起,则后续的读操作会被忽略。
*/
@Override
Channel read();
/**
* 将之前写入到发送环形数组中的消息全部写入到目标Chanel中,发送给通信对方
*/
@Override
Channel flush();
}
AbstractChannel
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
// 父Channel
private final Channel parent;
// Channel的全局唯一标识
private final ChannelId id;
// 内部辅助类 Unsafe
private final Unsafe unsafe;
// Netty 会为每一个 channel 创建一个 pipeline
private final DefaultChannelPipeline pipeline;
// 本地地址
private volatile SocketAddress localAddress;
// 远程主机地址
private volatile SocketAddress remoteAddress;
// 注册到了哪个 EventLoop 上
private volatile EventLoop eventLoop;
// 是否已注册
private volatile boolean registered;
/**
* channnel 会将 网络IO操作 触发到 ChannelPipeline 对应的事件方法。
* Netty 基于事件驱动,我们也可以理解为当 Chnanel 进行 IO操作 时会产生对应的IO 事件,
* 然后驱动事件在 ChannelPipeline 中传播,由对应的 ChannelHandler 对事件进行拦截和处理,
* 不关心的事件可以直接忽略
*/
@Override
public ChannelFuture bind(SocketAddress localAddress) {
return pipeline.bind(localAddress);
}
@Override
public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
return pipeline.bind(localAddress, promise);
}
@Override
public ChannelFuture connect(SocketAddress remoteAddress) {
return pipeline.connect(remoteAddress);
}
@Override
public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) {
return pipeline.connect(remoteAddress, localAddress);
}
@Override
public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) {
return pipeline.connect(remoteAddress, promise);
}
@Override
public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
return pipeline.connect(remoteAddress, localAddress, promise);
}
@Override
public ChannelFuture disconnect() {
return pipeline.disconnect();
}
@Override
public ChannelFuture disconnect(ChannelPromise promise) {
return pipeline.disconnect(promise);
}
@Override
public ChannelFuture close() {
return pipeline.close();
}
@Override
public ChannelFuture close(ChannelPromise promise) {
return pipeline.close(promise);
}
@Override
public ChannelFuture deregister() {
return pipeline.deregister();
}
@Override
public ChannelFuture deregister(ChannelPromise promise) {
return pipeline.deregister(promise);
}
@Override
public Channel flush() {
pipeline.flush();
return this;
}
@Override
public Channel read() {
pipeline.read();
return this;
}
@Override
public ChannelFuture write(Object msg) {
return pipeline.write(msg);
}
@Override
public ChannelFuture write(Object msg, ChannelPromise promise) {
return pipeline.write(msg, promise);
}
@Override
public ChannelFuture writeAndFlush(Object msg) {
return pipeline.writeAndFlush(msg);
}
@Override
public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {
return pipeline.writeAndFlush(msg, promise);
}
}
AbstractNioChannel
public abstract class AbstractNioChannel extends AbstractChannel {
// AbstractNioChannel 是 NioSocketChannel和NioServerSocketChannel 的公共父类,所以定义
// 了一个 java.nio 的 SocketChannel 和 ServerSocketChannel 的公共父类 SelectableChannel,
// 用于设置 SelectableChannel参数 和进行 IO操作
private final SelectableChannel ch;
// 它代表了 JDK 的 SelectionKey.OP_READ
protected final int readInterestOp;
// 该 SelectionKey 是 Channel 注册到 EventLoop 后返回的,
// 由于 Channel 会面临多个业务线程的并发写操作,当 SelectionKey 被修改了,
// 需要让其他业务线程感知到变化,所以使用volatile保证修改的可见性
volatile SelectionKey selectionKey;
/**
* Channel 的注册
*/
@Override
protected void doRegister() throws Exception {
boolean selected = false;
for (;;) {
try {
selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
return;
} catch (CancelledKeyException e) {
if (!selected) {
// Force the Selector to select now as the "canceled" SelectionKey may still be
// cached and not removed because no Select.select(..) operation was called yet.