Channel 组件和Unsafe接口

类似于 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.
                 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小新杂谈社

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值