NIO网络模型

1. NIO简介

NIO:Non-blocking I/O 或 New I/O

  • 从特性出发:非阻塞IO
  • 从年龄出发:新IO,在原始IO之后出现的

诞生:从 JDK 1.4 引入的全新的输入输出标准库,重新设计的一套IO标准

职务:高并发网络服务器支持岗。作为原始IO的补充,为了应对高性能高并发的应用场景。

2. 编程模型

模型:对事物共性的抽象(个人理解:用一个统一的方法解决一系列相似的问题)

编程模型:对编程共性的抽象(个人理解:用一个统一的编程方法解决一系列相似的问题)

2.1 BIO网络模型

BIO:Blocking I/O,阻塞IO。

传统的 BIO 通过socket.read()读取服务端的数据,如果TCP RecvBuffer里没有数据,函数会一直阻塞,直到收到数据,返回读到的数据。

在这里插入图片描述
在这里插入图片描述

当有很多客户端访问服务端,但客户端未发送数据,服务端线程处于线程阻塞,等待客户端响应,这样可能会导致服务端崩溃。

在大量并发的情况下,接入的客户端过多,会出现问题。

BIO网络模型的缺点:

  • 阻塞式I/O模型。(服务端必须等待客户端的再次请求)
  • 弹性伸缩能力差。(客户端与服务端的线程数时 1:1 的关系)
  • 多线程耗资源(线程创建、销毁,或大量线程处于服务器端都会使得服务端的CPU调度资源受到影响)
2.2 NIO网络模型

在这里插入图片描述

selector:负责管理与客户端建立的多个连接,负责监听注册到上面的一些事件,如有新连接接入、当前连接上有可读消息或可写消息。一旦事件被其监听到,就会调用对应的事件处理器来完成对事件的响应。

主要功能:接收所有与客户端socket的连接,并且监听它们关心的事件,当这个事件发生之后,就会调用相应的事件处理器来处理这个事件。

2.3 NIO网络模型改进
  • 非阻塞式I/O模型。(服务器端提供一个单线程的Selector来统一管理客户端socket接入的所有连接,并负责每个连接所关心的事件)
  • 弹性伸缩能力强。(服务器端不再是通过多个线程来处理请求,而是通过一个线程来处理所有请求,对应关系变为 N:1)
  • 单线程节省资源。(线程频繁创建、销毁,线程之间的上下文切换等带来的资源消耗得要缓解)

3. NIO网络编程详解

NIO核心类

  • Channel:通道
  • Buffer:缓冲区
  • Selector:选择器 或 多路复用器
3.1 Channel简介
3.1.1 Channe特性

(1)双向性

​ Channel是信息传输的通道,是 JDK NIO中对输入输出方式的另一种抽象,可以类比BIO中的流的概念。但与流不同的是,流是单向传输,有InputStream()、OutputStream(),而Channel是双向传输,即可读,又可写。

(2)非阻塞性

​ Channel可以工作在非阻塞模式下,正是由于这个特性,构成了NIO的基础。

(3)操作唯一性

​ 操作Channel的唯一方式是使用Buffer,通过Buffer操作Channel实现数据块的读写。Buffer本质上就是一个字节数组。

3.1.2 Channel核心实现类
  • 文件类:FileChannel
  • UDP类:DatagramChannel
  • TCP类:ServerSocketChannel / SocketChannel

Socket回顾:

/********** 服务端 **********/

// 1. 监听端口
ServerSocket serverSocket = new ServerSocket(8000);
while (true) {
    // 2. 接收请求,建立连接
    Socket socket = serverSocket.accept();
    // 3. 数据交换
    new Thread(new BIOServerHandler(socket)).start();
}
// 4. 关闭资源
serverSocket.close();


/********** 客户端 **********/

// 1. 建立连接
Socket socket = new Socket("127.0.0.1", 8000);
// 2. 获取输入输出流
InputStream inputStream = socket.getInputStream();
OutputStream outStream = socket.getOutputStream();

Channel使用:

// 代码片段 1:服务器端通过服务器socket创建channel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// 代码片段 2:服务器端绑定端口
serverSocketChannel.bind(new InetSocketAddress(8000));
// 代码片段 3:服务器端监听客户端连接,建立socketChannel连接
SocketChannel socketChannel = serverSocketChannel.accept();
// 代买片段 4:客户端连接远程主机及端口
SocketChannel socketChannel = SocketChannel.open(
    new InetSocketAddress("127.0.0.1", 8000))
3.2 Buffer简介

​ 提供唯一与Channel进行交互的方式。

  • 作用:读写Channel中的数据
  • 本质:一块可以从中读取或写入的内存区域。被NIO包装成一个NIO Buffer对象,并提供一组便于操作内存的方法。
3.2.1 Buffer属性

(1)Capacity:容量。

标明数组可以容纳的最大字节长度,若超出容量,则需要将其清空后才能重新写入。

(2)Position:位置

写模式:表示当前的位置,初始位置为0,最大值为 Capacity-1

读模式:重置为0

(3)Limit:上限

写模式:最多能往Buffer中写的数据数量,此时等于Capacity

读模式:此时等于写模式下的Position值。

(4)Mark:标记

标记一个特定Position位置,可通过Buffer的Reset()方法恢复到标记位置。

3.2.2 Buffer使用
// 初始化长度为10的byte类型Buffer
ByteBuffer.allocate(10);

在这里插入图片描述

// 向byteBuffer中写入三个字节
byteBuffer.put("abc".getBytes(Charset.forName("UTF-8")));

在这里插入图片描述

// 将byteBuffer从写模式切换成读模式
byteBuffer.flip();

在这里插入图片描述

// 从byteBuffer中读取一个字节
byteBuffer.get();

在这里插入图片描述

// 调用mark方法记录下当前position的位置
byteBuffer.mark();

在这里插入图片描述

// 先调用get方法读取下一个字节
byteBuffer.get()
// 再调用reset()方法将position重置到mark位置
byteBuffer.reset()

在这里插入图片描述

// 调用clear方法,将所有属性重置
byteBuffer.clear()

在这里插入图片描述

3.3 Selector简介

Java NIO中能够检测1到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件。由Selector就能通过一个单独的线程来管理多个Channel,从而管理多个网络连接。

3.3.1 Selector使用
// 代码片段 1:创建Selector
Selector selector = Selector.open();
// 代码片段 2:将channel注册到selector上,监听读就绪事件
SelectionKey selectionKey = channel.register(selector, SelectionKey.OP_READ);
// 代码片段 3:阻塞等待channel的就绪事件发生
int selectNum = selector.select();
// 代码片段 4:获取发生就绪事件的channel集合
Set<SelectionKey> selectedKeys = selector.selectedKeys();
3.3.2 SelectionKey简介

(1)四种就绪状态常量

SelectionKey常量提供了四个可监听事件的静态常量值。

  • OP_CONNECT:连接就绪。连接操作,Client端支持的一种操作
  • OP_ACCEPT:接收就绪。连接可接受操作,仅ServerSocketChannel支持
  • OP_READ:读就绪。
  • OP_WRITE:写就绪。

(2)可以获取有价值的属性

在调用Selector对象的SelectedKey方法时,会返回一个SelectionKey的集合。可以通过这个SelectionKey的集合获取当前的Channel、当前Selector的对象、Channel已就绪事件集合和所关心事件集合。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值