04-Channel接口

Channel接口

  • Channel在Netty中描述成一个网络插座,具备连接,绑定,读写等功能,下面部分是Netty源码中Channel接口的注释。
+ 并且所有的IO操作都是异步的,操作都会立即返回,通过Netty的Future接口(可能是不通的子类,比如ChannelFuture)来获取结果,

+ Channel是具备等级的,一个Channel可以有一个parent,这取决于这个Channel是如何创建的,比如说,当ServerSocketChannel通
过accept()方法接受一个SocketChannel时,那么SocketChannel的父亲是ServerSocketChannel,调用SocketChannel的parent()方法
返回该ServerSocketChannel对象。 

+ 可以使用向下转型访问特点的传输方法,某些子类Channel会提供一些所需的特定操作,可以向下转型到这样的子类,从而获得特定
操作。比如说,对于UDP的数据报的传输,有特定的join()和leave()操作,我们可以向下转型到DatagramChannel从而使用这些操作。 

+ 当Channel不使用是,通过close方法释放资源

一、ChannelOutboundInvoker

  • ChannelOutboundInvoker是Channel的父接口,定义了相关的基本操作,部分方法如下:
public interface ChannelOutboundInvoker {

    /**
     * 绑定到指定地址,完成后会通知ChannelFuture,不管成功或者失败
     */
    ChannelFuture bind(SocketAddress localAddress);

    /**
     * 连接到指定地址,操作完成后通知ChannelFuture,不管成功或者失败
     */
    ChannelFuture connect(SocketAddress remoteAddress);

    /**
     * 请求断开连接,操作完成后通知ChannelFuture,不管成功或者失败
     */
    ChannelFuture disconnect();

    /**
     * 关闭Channel,完成后通知ChannelFuture,不管成功或者失败
     */
    ChannelFuture close();

    /**
     * 将Channel从EventExecutor注销,完成后会通知ChannelFuture,,不管成功或者失败
     */
    ChannelFuture deregister();
 
    /**
     * 断开连接
     */
    ChannelFuture disconnect(ChannelPromise promise);

    /**
     * 关闭
     */
    ChannelFuture close(ChannelPromise promise);

    /**
     * 注销
     */
    ChannelFuture deregister(ChannelPromise promise);

    /**
     * 从Channel读数据到入站buffer,如果读到数据就触发一次channelRead事件,如果可以继续读取数据会触发channelReadComplete事件
     */
    ChannelOutboundInvoker read();

    /**
     * 请求通过ChannelPipeline写数据 不会触发flush
     */
    ChannelFuture write(Object msg);

    /**
     * 返回成功的ChannelFuture
     */
    ChannelFuture newSucceededFuture();

    /**
     * 返回失败的ChannelFuture
     */
    ChannelFuture newFailedFuture(Throwable cause);
}

二、Channel

2.1 接口方法

  • 下面是Channel接口里面的方法
public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel> {

    /**
     * 返回Channel的编号id
     */
    ChannelId id();

    /**
     * 返回Channel注册到的EventLoop对象
     */
    EventLoop eventLoop();

    /**
     * 返回父Channel对象
     */
    Channel parent();

    /**
     * 返回Channel配置参数
     */
    ChannelConfig config();

    /**
     * 判断Channel是否打开。
     */
    boolean isOpen();

    /**
     * 判断Channel是否注册
     */
    boolean isRegistered();

    /**
     * 判断Channel是否激活
     * 对于服务端 ServerSocketChannel ,true 表示 Channel 已经绑定到端口上,可提供服务
     * 对于客户端 SocketChannel ,true 表示 Channel 连接到远程服务器
     */
    boolean isActive();

    /**
     * 返回Channel的元数据,元数据描述了Channel
     */
    ChannelMetadata metadata();

    /**
     * 返回Channel绑定的本地地址
     */
    SocketAddress localAddress();

    /**
     * 返回Channel连接的远端地址
     */
    SocketAddress remoteAddress();

    /**
     * Channel关闭时会调用的Future对象,总是会返回一个对象
     */
    ChannelFuture closeFuture();

    /**
     * Channel 是否可写
     * 当 Channel 的写缓存区 outbound 非 null 且可写时,返回 true
     */
    boolean isWritable();

    /**
     * 获得距离不可写还有多少字节数,总会返回一个正数,如果不可写了就会返回0
     */
    long bytesBeforeUnwritable();

    /**
     * 获得距离可写还要多少字节数,总会返回一个正数,如果可写了就会返回0
     */
    long bytesBeforeWritable();

    /**
     * Unsafe 对象
     */
    Unsafe unsafe();

    /**
     * 返回Channel对应所属的ChannelPipeline对象,用于处理 Inbound 和 Outbound 事件的处理
     */
    ChannelPipeline pipeline();

    /**
     * ByteBuf分配器
     */
    ByteBufAllocator alloc();

    @Override
    Channel read();

    @Override
    Channel flush();
}

将方法稍微整理一下看的更清楚些:

方法分类方法
状态判断isOpen、isRegistered、isActive、isWritable
属性获取id、eventLoop、parent、config、、metadata、localAddress、remoteAddress、unsafe、pipeline、alloc、voidPromise
结果获取closeFuture、newPromise、newSucceededFuture、newFailedFuture
IO相关bind、connect、disconnect、close、deregister、read、write、flush、writeAndFlush

2.2 Unsafe接口

  • 在Unsafe接口中有部分和ChannelOutboundInvoker接口一样的方法,比如register、bind、flush、read、write等。实际上Unsafe作为Channel的内部类,负责处理底层NIO相关的I/O事件,Channel则使用责任链的方式通过ChannelPipeline将事件提供给用户自定义处理。
  • Unsafe直译是不安全,其实这个不安全是指程序员一般不要直接使用它,它通常是程序所使用的接口方法的内部或者底层实现。
interface Unsafe {
        /**
         * ByteBuf 分配器的处理器
         */
        RecvByteBufAllocator.Handle recvBufAllocHandle();

        /**
         * 本地地址
         */
        SocketAddress localAddress();

        /**
         * 远端地址
         */
        SocketAddress remoteAddress();

        /**
         * 注册,注册成功后会通知ChannelPromise的
         */
        void register(EventLoop eventLoop, ChannelPromise promise);

        /**
         * 绑定到本地地址,并且绑定成后通知ChannelPromise
         */
        void bind(SocketAddress localAddress, ChannelPromise promise);

        /**
         * 连接远程地址,从ChannelPromise获取结果
         */
        void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);

        /**
         * 断开连接,成功断开后会通知ChannelPromise
         */
        void disconnect(ChannelPromise promise);

        /**
         * 关闭连接,成功后会通知ChannelPromise
         */
        void close(ChannelPromise promise);

        /**
         * 立刻断开Channel,不触发任何时间,可能在注册失败的时候有用
         */
        void closeForcibly();

        /**
         * 将Channel从EventLoop注销,成功完成后通知ChannelPromise
         */
        void deregister(ChannelPromise promise);

        /**
         * 当ChannelPipeline中第一个ChannelInboundHandler的buffer被填满的时候,执行一个读操作,如果已经有读操作了就不做任何事情
         */
        void beginRead();

        /**
         * Schedules a write operation. 执行一个写操作
         */
        void write(Object msg, ChannelPromise promise);

        /**
         * flush所有的write操作
         */
        void flush();

        ChannelPromise voidPromise();

        ChannelOutboundBuffer outboundBuffer();
    }

三、Channel子接口

在这里插入图片描述

  • Channel接口是非常抽象的,而且根据不同的底层操作系统平台,在实现上可能又会有差异,因此其对应的继承关系非常复杂,从继承图中可以看到,在Netty中其子接口非常多,实现类也会有很多,这里我们先看看其子接口,下一篇文章再看实现类。

3.1 AbstractChannel

  • Channel接口的骨架实现

3.2 DuplexChannel

  • DuplexChannel代表双边通信Channel,两个方向通信可以独立关闭

3.3 UnixChannel

  • UnixChannel是暴露给类Unix系统去实现的api

3.4 ServerChannel

  • ServerChannel没有定义任何的接口方法,只是一个标记接口,ServerChannel可以接受连接并创建子Channel来接受连接,ServerSocketChannel是最好的例子

3.5 SctpChannel

  • SctpChannel是一种面向消息的连接传输,支持多流和多宿主。有NioSctpChannel和OioSctpChannel两个实现类

3.6 DatagramChannel

  • DatagramChannel代表UDP的Channel通道

3.7 Http2StreamChannel

  • Http2StreamChannel使用很少,实现类也很少,

  • 后续的文章中,我们按照子接口的分类来阅读源码,比如我们可以从DuplexChannel的SocketChannel来看看它有哪些子类,SocketChannel代表客户端的Channle通道,后面会看到SocketChannel有NioSocketChannel、OioSocketChannel、EpollSocketChannel和KQueueSocketChannel这几个实现类,并且这四个实现类都继承了骨架抽象类AbstractChannel,这种设计非常经典,接口一层一层继承,然后衍生出不同类型的子接口,通过模板模式先实现骨架,子类继承骨架抽象类然重写实现自己的特殊方法。另外一个很重要的接口就是ServerChannel,它标记了服务端的Channel通道,后续我们都慢慢分析。

  • 下面补充一张SocketChannel的继承图,可以看出四个子类实现了SocketChannel接口,并且都继承了AbstractChannel。

在这里插入图片描述

四、参考

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值