您当前的位置: 首页 > 

恐龙弟旺仔

暂无认证

  • 0浏览

    0关注

    282博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Netty源码解析-Netty之Channel初探

恐龙弟旺仔 发布时间:2021-12-27 18:58:14 ,浏览量:0

前言:

    了解完前面的知识块,也就是最开始的文章中说的

    * EventLoop和EventLoopGroup

    * ChannelHandler与ChannelPipeline

    * ByteBuf与ByteBufAllocator

    这些大块以后,我们可以看下最核心的模块:Channel。基本所有重要的工作,注册、获取连接、读写都是Channel在执行。

    本文主要对Channel接口的基本功能进行介绍,对其相关实现类进行简单介绍。后面会专门提供两篇文章来聊下我们最关心的NioServerSocketChannel和NioServerSocketChannel。

1.Channel接口基本方法

    该Channel是Netty提供的,全限定名为io.netty.channel.Channel。JDK NIO中也提供了一个Channel,全限定名为java.nio.channels.Channel,这个Channel作为一个通道与网络或文件进行操作。

    而Netty中提供的Channel,我们也可以理解为一个通道,只不过这个通道的功能比较强大。

// A nexus to a network socket or a component which is capable of I/O operations 
// such as read, write, connect, and bind.
package io.netty.channel;
public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable {
    // 编号
    ChannelId id();
    // 当前channel所属EventLoop,归哪个线程来执行
    EventLoop eventLoop();
    
    // 基本属性
    ChannelConfig config();
    // channel所绑定的本地地址
    SocketAddress localAddress();
    // channel绑定的远程地址
    SocketAddress remoteAddress();
    
    // 很重要的Unsfae对象,一个Channel对应一个Unsafe
    Unsafe unsafe();
    // 所属pipeline
    ChannelPipeline pipeline();
    // 所属ByteBuf分配器
    ByteBufAllocator alloc();
    
    
    /** 状态相关 */
    boolean isOpen();
    boolean isRegistered();
    boolean isActive();
    boolean isWritable();
    
    /** 方法相关 */
    Channel read();
    Channel flush();
    
    // 内部接口类Unsafe
    interface Unsafe {
        // 主要方法如下
		void register(EventLoop eventLoop, ChannelPromise promise);   
        void bind(SocketAddress localAddress, ChannelPromise promise);
        void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);
        void write(Object msg, ChannelPromise promise);
    }
}

而关于继承的ChannelOutboundInvoker,有以下方法提供,这个我们比较熟悉了。

方法返回都是ChannelFuture,基本都是异步执行

public interface ChannelOutboundInvoker {
    ChannelFuture bind(SocketAddress localAddress);
    ChannelFuture connect(SocketAddress remoteAddress);
    ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress);
    ChannelFuture disconnect();
    ChannelFuture close();
    ChannelFuture deregister();
    ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise);
    ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise);
    ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);
    ChannelFuture disconnect(ChannelPromise promise);
    ChannelFuture close(ChannelPromise promise);
    ChannelFuture deregister(ChannelPromise promise);
    ChannelOutboundInvoker read();
    ChannelFuture write(Object msg);
    ChannelFuture write(Object msg, ChannelPromise promise);
    ChannelOutboundInvoker flush();
    ChannelFuture writeAndFlush(Object msg, ChannelPromise promise);
    ChannelFuture writeAndFlush(Object msg);
}

这些方法综合起来,相当于Channel提供了一个全量的网络操作。

2.Channel的实现类结构图

    Channel作为一个接口类,它的实现类主要有以下这些

当然以上主要都是基于NIO的实现。除了NIO,还有其他实现,如下图(图片来自网络)

我们今天主要讨论NIO的相关实现。

2.1 SocketChannel

    SocketChannel作为客户端的Channel接口类,主要提供了以下方法

/**
 * A TCP/IP socket {@link Channel}.
 */
public interface SocketChannel extends DuplexChannel {
    @Override
    ServerSocketChannel parent();

    @Override
    SocketChannelConfig config();
    // 就是返回类编程实现类了
    InetSocketAddress localAddress();
    @Override
    InetSocketAddress remoteAddress();
}

// 主要的与Channel的不同点在于DuplexChannel
public interface DuplexChannel extends Channel {
    // 对输入输出流的操作
    boolean isInputShutdown();
    ChannelFuture shutdownInput();
    ChannelFuture shutdownInput(ChannelPromise promise);
    boolean isOutputShutdown();
    ChannelFuture shutdownOutput();
    ChannelFuture shutdownOutput(ChannelPromise promise);
    boolean isShutdown();
    ChannelFuture shutdown();
    ChannelFuture shutdown(ChannelPromise promise);
}

所以,SocketChannel相对于Channel而言,主要是提供了关闭输入输出流的API

2.2 ServerSocketChannel
/**
 * A TCP/IP {@link ServerChannel} which accepts incoming TCP/IP connections.
 */
public interface ServerSocketChannel extends ServerChannel {
    @Override
    ServerSocketChannelConfig config();
    // 就是返回对象变成了实体类
    InetSocketAddress localAddress();
    @Override
    InetSocketAddress remoteAddress();
}

// 一个标记接口
public interface ServerChannel extends Channel {
    // This is a tag interface.
}

这个接口貌似就没什么特别的API了

3.Unsafe内部接口类

Channel.Unsafe就是一个比较神奇的设计了。有点类似于JDK中sun.misc.Unsafe类。这个类官方不建议直接调用,而是让我们使用它的封装类来间接调用。

而这个Unsafe也是,Netty中也不建议我们直接使用它,而是实现它的封装类。我们来看下它的注解,就知道官方的良苦用心了。

/**
     * Unsafe operations that should never be called from user-code. These methods
     * are only provided to implement the actual transport, and must be invoked from an I/O thread except for the
     * following methods:
*/
interface Unsafe {}

关注
打赏
1655041699
查看更多评论
立即登录/注册

微信扫码登录

0.0357s