NIO 三大组件之Channel

NIO 三大组件

  • Channel
    • FileChannelel
    • ServerSocketChannel
    • SocketChannel
    • DatagramChannel
  • Buffer
  • Selector

阻塞I/O与非阻塞I/O

  • 非阻塞 I/O
    • NIO 中的非阻塞I/O是基于 Reactor 模式的,在这里I/O的调用是不会阻塞的,相反是注册感兴趣的I/O事件。如可读数据到达,便会发生触发事件。NIO 中实现非阻塞I/O的核心对象是Selector。而 Selector就是注册各种事件的地方。非阻塞I/O指的是I/O事件本身不阻塞,但是获取事件的select()方法是需要阻塞等待的。而阻塞I/O则是阻塞在I/O操作上。NIO是阻塞在事件的获取上,没有事件就没有I/O,从这个层面看,I/O就是不会阻塞的了。

Channel

channel字面上便是“通道”的意思,它和IO中的Stream流是相似的,但是Stream是单向的,而Channel则是双向的(可以进行读/取操作)。NIO中 Channel 的实现有:FileChannel、DatagramChannel、SocketChannel、ServerSocketChannel。

NIO 中通过Channel 封装了对数据源的操作,这样便可以操作数据源,但又不必关心数据源的具体物理结构。channel与文件描述符或socket是相对应的。Channel用于在字节缓冲区和位于通道另一侧的实体之间有效的传输数据。

public interface Channel extends Closeable {
    
    public boolean isOpen();

    public void close() throws IOException;

}

与缓冲区不同,通道是一个接口定义,在不同的操作系统上有不同的实现,这样也 就会有一定的差异。因此在Channel接口中只是定义了它具有上面作用的方法。

同时Channel是一个对象,可以通过它读取和写入数据,而所有的数据都是通过Buffer来处理的。这样便不会将字节直接写入通道中,还有这里不会直接从通道中读取字节,而是将数据从通道读入缓冲区,然后再从缓冲区中读取。

Java NIO的通道类似流,但又有所不同:

  • 既可以从通道中读取数据,也可以写数据到通道中,但是流到操作是单向的
  • 通道可以异步的读写
  • 通道中的数据总要先读到一个buffer,或者总是要从一个buffer中写入

Java NIO 中最重要的 Channel 的实现:

  1. FileChannel 从文件中读写数据
  2. DatagramChannel 能通过 UDP 读写网络中的数据
  3. SocketChannel 能通过 TCP 读写网络中的数据
  4. ServerSocketChannel 可以监听新进来的 TCP 连接,像 Web 服务器那样。对

每一个新进来的连接都会创建一个 SocketChannel。

FileChannel

public abstract class FileChannel
    extends AbstractInterruptibleChannel
    implements SeekableByteChannel, GatheringByteChannel, ScatteringByteChannel
{
    // 省略
}

从上面的代码和图片中可以看出,FileChannel类分别继承了 AbstractInterruptibleChannel 和 实现了SeekableByteChannel,、GatheringByteChannel、ScatteringByteChannel,这里可以看下FileChannel类结构图:

从类结构图中可以清晰的看出,FileChannel类具有read,write的作用,是因为它实现了WritableByteChannel和ReadableByteChannel(这也说明通道只能在字节缓冲区上操作)。FileChannel 继承的 AbstractInterruptibleChannel 所实现的 InterruptibleChannel 类是一个具有异步关闭和终端功能的通道,因此 FileChannel 类也是具备这个能力的。

SocketChannel

public abstract class SocketChannel
    extends AbstractSelectableChannel
    implements ByteChannel, ScatteringByteChannel, GatheringByteChannel, NetworkChannel
{
    // 省略
}

从类结构图上可以看出 SocketChannel 继承自 AbstractSelectableChannel,而 AbstractSelectableChannel 有继承了SelectableChannel,AbstractSelectableChannel 类是基于 SelectableChannel 进行进一步的抽象,SelectableChannel是一个具有多路复用的Channel类。SelectableChannel 也是继承了 AbstractInterruptibleChannel 类,这说明它和 FileChannel 一样具有异步关闭和终端的功能。不过这里可以看出 SocketChannel 实现了NetworkChannel 接口,NetworkChannel 代码如下:

public interface NetworkChannel
    extends Channel
{
    // 绑定地址到 NetworkChannel
    NetworkChannel bind(SocketAddress local) throws IOException;

    // 获取本地地址
    SocketAddress getLocalAddress() throws IOException;

    // 设置 SocketOption 的值
    <T> NetworkChannel setOption(SocketOption<T> name, T value) throws IOException;

    // 返回一个 SocketOption
    <T> T getOption(SocketOption<T> name) throws IOException;

    // 返回次通道的一组 SocketOption
    Set<SocketOption<?>> supportedOptions();
}

DatagramChannel

public abstract class DatagramChannel
    extends AbstractSelectableChannel
    implements ByteChannel, ScatteringByteChannel, GatheringByteChannel, MulticastChannel
{
    // 省略
}

DatagramChannel 所实现的接口和SocketChannel是一样了(除了多了个 MulticastChannel),DatagramChannel 也和SocketChannel 一样继承了 AbstractSelectableChannel,那么这里就只关注MulticastChannel接口,代码如下:

public interface MulticastChannel
    extends NetworkChannel
{
    @Override void close() throws IOException;

    MembershipKey join(InetAddress group, NetworkInterface interf)
        throws IOException;

    MembershipKey join(InetAddress group, NetworkInterface interf, InetAddress source)
        throws IOException;
}

MulticastChannel是一个支持互联网协议组播的网络通道接口,它里面定义了关闭通道、join等方法。

ServerSocketChannel

public abstract class ServerSocketChannel
    extends AbstractSelectableChannel
    implements NetworkChannel
{
    // 省略
}

ServerSocketChannel 负责监听传入的连接和创建新的 SocketChannel 对象,它本身从不传输数据。

猜你喜欢

转载自blog.csdn.net/zfy163520/article/details/121777442