2、大白话分析BIO,NIO,AIO

章节概览

Netty源码分析章节概览


1、概述

上一篇文章一分钟弄懂同步,异步,阻塞,非阻塞简单的了解了下同步,异步,阻塞,非阻塞的概念。那么在java的网络编程中,这些不同的IO状态又是怎么规划的呢。为了深入的理解这个问题。我们参考了《Netty 权威指南》 部分章节进行详细说明。深入理解不同的IO网络流的情况。同时进一步分析下BIO的原理。


2、Linux网络模型简介

Linux的内核将所有的外部设备都看做成一个文件来操作,对一个文件的读写操作都会调用内核提供的系统指令,返回一个file descriptor(fd,文件描述符)。而Socket的读写也会有相应的描述符,称之为socketfd (socket描述符),这里所说的描述符就是一个数字,指向内核中的一个结构体(文件路径,数据区)。

Unix网络编程对I/O模型进行了详细的分类,Unix 提供了5种不同的模型,下面我们依次分析这五种模型。

2.1、 阻塞IO模型

在这里插入图片描述
阻塞IO是最常用的IO模型,在缺省的情况下,所有文件操作都是阻塞的。这里的应用进程就是我们所说的客户端,而内核系统就是我们服务端。简化以后我们看下整个流程。客户端调用服务端请求数据,服务端收到客户端的请求过后,首先会检查其内核中是否有数据,没有数据就一直等待。等待内核中有数据之后,将内核中的数据发送给客户端。

流程分析:
整个过程客户端请求服务端的过程中,一直处于阻塞状态。而服务端对于客户端来说是同步的(同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为),客户端必须等待其执行结果。而不是服务端拿到数据之后异步通知。

总结:
所以阻塞IO是一个同步阻塞的IO。

2.2、 非阻塞IO模型

在这里插入图片描述
非阻塞IO,客户端调用服务器获取数据,如果服务端(内核缓冲区)中没有数据,直接返回EWOULDBLOCK错误,此时客户端不断的轮询服务端是否有数据准备好。如果服务端有数据准备好了,直接复制数据。

流程分析:整个非阻塞IO和阻塞IO的区别就是,客户端去请求数据。在阻塞模式下,客户端一直等待,任何事情都不去做。而在非阻塞模式下,客户端隔段时间去看下有没有数据完成,那么这个过程中,中间间隔的时间,就可以去做一下自己想做的事情。当然整个过程中,服务端还是同步的。

总结:通过上面的分析,异步IO模式是:同步非阻塞

2.3、 I/O复用模型

在这里插入图片描述
IO复用模型,Linux提供了select/poll/epoll,进程通过将一个或者多个fd传递给select或者poll系统调用。阻塞在select操作上,这样select/poll 可以帮助我们侦测多个fd是否处于就绪状态。由于select/poll是顺序扫描fd是否就绪,而且支持fd的数量是有限制的。Linux还提供了一个epoll系统调用。epoll使用是基于事件驱动方式代替顺序扫描,因此性能更高。

在Linux中,所有的设备操作都是操作文件,所以每个socket连接,相当于操作一个socketfd。在同步阻塞的IO中,为了提高并发度,会为每个socket连接分配一个线程去处理。这样在高并发的情况下,导致系统存在大量的线程,从而使可用性下降。为了解决这个问题,Linux底层把那些建立起连接的socketfd,提交给系统底层的epoll进行管理。每次系统调用的时候,只会把那些已经发生某些事件的socket连接批量发送给客户端,在这种情况下只需要用一个线程去监控所有socket可能存在的状态。把那些已经发生事件的socket提取出来,放到一个list集合中,批量发送给客户端。客户端根据socket的具体事件,去做相应的处理。

这个也是netty底层所实现的核心思想

总结:linux系统将已经发生事件的socket连接,打包发送给客户端。客户端在调用的时候,只需要拿到那些发生事件的socket,然后进行处理。

2.4、信号驱动I/O模型

在这里插入图片描述
首先开启套接口信号驱动I/O功能,并通过系统调用singaction执行一个信号处理函数(此系统调用,理解返回,进程继续工作,它是非阻塞的)。当数据准备就绪时,就为该进程生产一个sigio信号,通过信号回调通知应用程序调用recvfrom来读取数据。并通知主循环函数处理数据。

总结:整个过程,客户端处于非阻塞状态,服务端有数据的时候,通知客户端获取数据,是异步状态。所以信号驱动I/O模型是异步非阻塞模型。

2.5 异步 I/O

在这里插入图片描述
客户端告知服务端要启动某个操作,并让内核在整个操作完成一个(包括数据从内核复制到用户空间)通知我们。这种模式与信号驱动的主要区别是:信号驱动由内核通知我们合适开始一个I/O操作,用户还是需要自己去调用recvfrom,去拷贝数据(从内核空间拷贝到用户空间)。而异步I/O已经完成了所有的动作,通知用户去获取数据即可。


3、小结

通过上面的分析,加上自己的理解。介绍了Linux网络编程的5种模式。Java的网络编程就是在此基础上进行封装的。后面我们依次通过代码案例分析Java中的IO编程操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值