Netty学习前置知识:NIO三大组件

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

一、前言

在上一篇文章中我们学习了几种IO模型由于Netty是基于NIO实现的所以我们今天继续学习NIO的相关知识今天的主题是NIO的三大组件Selector、Buffer、Channel。

二、NIO三大组件

一个NIO Demo

在讲述NIO三大组件之前让我们先看一个基于NIO的Demo

public class Test {

    public static void main(String[] args) throws Exception {
        FileInputStream inputStream = new FileInputStream("C:\\Users\\Administrator\\Desktop\\新建文本文档.txt");
        //获取一个channel
        FileChannel channel = inputStream.getChannel();
        //申请一块内存空间
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);
        while (true) {
            int b = channel.read(byteBuffer);
            if(b == -1){
                break;
            }
            //切换成读模式
            byteBuffer.flip();
            while(byteBuffer.hasRemaining()){
                byte bt = byteBuffer.get();
                System.out.println((char)bt);
            }
            //清空byte buff
            byteBuffer.clear();
        }

    }
}

案例中的代码非常简单实现的功能也就是从Txt中读取所有的内容然后挨个输出到控制台这里就体现了NIO是面向缓冲区这一特性。

NIO三大组件结构图

image.png

原谅我画图画的有点丑

1、Buffer

Buffer翻译成中文就是缓冲器想必你一定听过这样一句话NIO是面向缓冲区的怎么理解这句话呢个人的理解是在NIO中数据的通信都是基于Buffer来实现的。
image.png
从源码中我们可Buffer是一个抽象类他有许多子类例如我们上面用到的ByteBuffer这里我们就以ByteBuffer为例。
image.png 可以看到ByteBuffer中有一个byte类型的数组这是一片连续的内存空间在集合之前的代码中我们使用ByteBuffer byteBuffer = ByteBuffer.allocate(10)向操作系统申请一片大小为10个字节的连续内存空间用充当缓冲区。
再看这行代码 int b = channel.read(byteBuffer); 结合这上面的结构图其实也很好理解了channel想要获取数据就要通过buffer。这也就是为什么说 NIO是面向缓冲区的
小结

  • NIO中的Buffer是内存中一块连续的空间
  • NIO是面向缓冲区的

2、Channel

channel翻译成中文就是管道可以看到Channel是一个接口
image.png

A nexus for I/O operations.
A channel represents an open connection to an entity such as a hardware device, a file, a network socket, or a program component that is capable of performing one or more distinct I/O operations, for example reading or writing.
A channel is either open or closed. A channel is open upon creation, and once closed it remains closed. Once a channel is closed, any attempt to invoke an I/O operation upon it will cause a ClosedChannelException to be thrown. Whether or not a channel is open may be tested by invoking its isOpen method.
Channels are, in general, intended to be safe for multithreaded access as described in the specifications of the interfaces and classes that extend and implement this interface.
译文Channel关联IO操作的
通道表示与能够执行一个或多个不同I/O操作例如读取或写入的实体例如硬件设备、文件、网络套接字或程序组件的开放连接。
通道打开或关闭。通道在创建时打开一旦关闭它将保持关闭状态。一旦通道关闭任何对其调用I/O操作的尝试都会引发ClosedChannelException。可以通过调用其isOpen方法来测试通道是否打开。
通常通道对于多线程访问是安全的如扩展和实现该接口的接口和类的规范中所述。

这里我们以demo中FileChannel为例我们知道通常程序要读取数据和写数据需要分为两个流输入流和输出流而FileChannel即提供了读又提供了写这里我们不深究是如何读写的所以可以理解channel是对IO的封装。
image.png
小结简单的来说Channel就是对IO的封装并且对IO进行了增强一个Channel代表着一个连接。具体的之后放到netty学习中讲解毕竟实际工作中我们很少会直接使用JDK自带的NIO

3、Selector

在上一篇文章中我们知道了NIO中的多路复用模式这里要说的selector就是一个多路复用器。
image.png
从代码中看Selector是一个抽象类其中有一个比较重要的属性SelectionKey选择关键字从结构图中我们知道一个selector连接着多个channel那么不同的channel就会有不同的事件类型比如 channel1刚建立连接channel2已结开始读取数据。所以在SelectionKey中也有对应的4个事类型
image.png
OP_READ对应Channel的读操作
OP_WRITER对应Channel的写操作
OP_CONNECT对应Channel的连接操作
OP_ACCEPT用于支持选择器检测到相应的服务器套接字通道已准备好接受另一个连接或者有一个挂起的错误。
Selector会一直不断轮训所有的Channel并且根据不同的事件类型进行不同的处理。

三、总结

至此我们已经对NIO的三大组件有了一个初步的认识之后的文章会学习如何使用这些组件。希望对你有所帮助。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6