一、IO模型

同步、异步:

阻塞、非阻塞:

read的两步操作:

(1)等待数据准备。

(2)数据从内核空间拷贝到用户空间。

 

二、Unix提供的5种IO模型

    (1)阻塞    IO:调用了某个函数,等待该函数返回,期间什么都不做,一直检查该函数有没有返回。等到该函数有返回才可以进行下一步动作。

IO模型(一)

实现步骤

编程步骤:

服务端:

  1. 创建ServerSocket实例
  2. 绑定占用端口
  3. 通过accept()方法监听并等待客户端的连接
  4. 如果有客户端连接,则获得Socket实例
  5. 通过Socket实例进行读写操作
  6. 关闭资源和Socket

客户端:

  1. 创建Socket实例
  2. 通过connect()方法连接服务端
  3. 进行读写操作
  4. 关闭资源

    (2)非阻塞IO:非阻塞等待,每隔一段时间就去检测IO事件是否就绪。没有就绪就可以做其他事。

IO模型(一)

实现步骤:

服务端:

  1. 创建ServerSocketChannel实例(open)
  2. 对实例绑定端口(bind)
  3. 将实例设置为非阻塞(configureBlocking)
  4. 实例化selector选择器(open)
  5. 将ServerSocketChannel实例注册(register)到selector选择器,并关注可接受事件
  6. 选择器进行监听,有事件发生则返回
  7. 遍历感兴趣事件集合,判断是否有可接受事件
  8. 有可接受事件发生,获取对应通道,调用accept()方法获取SocketChannel实例
  9. SocketChannel实例设置为非阻塞,将其注册到选择器,并关注读事件
  10. 循环第6步,遍历集合,判断是否有可读事件发生
  11. 通过Buffer从channel读取数据
  12. 关闭打开的资源,包括selector选择器,关闭SocketChannel实例、ServerSocketChannel实例

客户端:

  1. 创建socketChanel实例
  2. 将socketChanel实例设置为非阻塞
  3. 创建selector实例
  4. 连接服务端,立即返回结果不成功,将chanel注册到选择器中,并关注可连接事件
  5. selector实例监听事件,有事件发生则返回
  6. 如该事件是可连接事件,则完成当前连接(finishConnect)
  7. 发送消息,接收消息
  8. 关闭资源

    (3)IO复用:inux用select/poll函数实现IO复用模型,这两个函数也会使进程阻塞,但是和阻塞IO所不同的是这两个函数可以同时阻塞多个IO操作。而且可以同时对多个读操作、写操作的IO函数进行检测。知道有数据可读或可写时,才真正调用IO操作函数

IO模型(一)
    (4)信号量:信号驱动IO:linux用套接口进行信号驱动IO,安装一个信号处理函数,进程继续运行并不阻塞,当IO时间就绪,进程收到SIGIO信号。然后处理IO事件。

IO模型(一)
    (5)异步IO:linux中,可以调用aio_read函数告诉内核描述字缓冲区指针和缓冲区的大小、文件偏移及通知的方式,然后立即返回,当内核将数据拷贝到缓冲区后,再通知应用程序。

IO模型(一)

三、区别

(1)BIO

BIO编程步骤:

服务端:
1、创建ServerSocket实例
2、绑定占用端口
3、通过accept()方法监听并等待客户端的连接
4、如果有客户端连接,则获得Socket实例
5、通过Socket实例进行读写操作
6、关闭资源和Socket

客户端:
1、创建Socket实例
2、通过connect()方法连接服务端
3、进行读写操作
4、关闭资源

可能阻塞的方法:accept()、connect()、read()、write()

BIO缺点:

本地操作系统占用,每次创建线程。多线程时线程切换,当瞬间并发量很大时,CPU或内存使用率高。

(2)NIO(同步非阻塞)

类似于IO复用模型,包括Channel(通道)、Buffer(缓存)、Selector(选择器/IO复用器)。

NIO编程步骤:

TCP:
ServerSocketChannel
SocketChannel

服务端:
1、创建ServerSocketChannel实例(open)
2、对实例绑定端口(bind)
3、将实例设置为非阻塞(configureBlocking)
4、实例化selector选择器(open)
5、将ServerSocketChannel实例注册(register)到selector选择器,并关注可接受事件
6、选择器进行监听,有事件发生则返回
7、遍历感兴趣事件集合,判断是否有可接受事件
8、有可接受事件发生,获取对应通道,调用accept()方法获取SocketChannel实例
9、SocketChannel实例设置为非阻塞,将其注册到选择器,并关注读事件
10、循环第6步,遍历集合,判断是否有可读事件发生
11、通过Buffer从channel读取数据
12、关闭打开的资源,包括selector选择器,关闭SocketChannel实例、ServerSocketChannel实例


客户端:
1、创建socketChanel实例
2、将socketChanel实例设置为非阻塞
3、创建selector实例
4、连接服务端,立即返回结果不成功,将chanel注册到选择器中,并关注可连接事件
5、selector实例监听事件,有事件发生则返回
6、如该事件是可连接事件,则完成当前连接(finishConnect)
7、发送消息,接收消息
8、关闭资源
 

(3)AIO(异步阻塞IO):

accept()方法:

 

BIO、NIO、AIO应用场景:

BIO 并发量固定的业务请求。
NIO 并发量高、业务逻辑简单(轻量级)——聊天
AIO 并发量高、业务逻辑复杂(重量级)

 

相关文章:

  • 2021-08-17
猜你喜欢
  • 2021-08-08
  • 2021-09-26
  • 2022-12-23
  • 2021-05-03
  • 2021-10-16
  • 2022-01-02
相关资源
相似解决方案