网络编程之IO:说到IO不得不会想到NIO和BIO,说到这两个概念我们不得不看一下两个:
stream就是咱们以前接触的文件输入输出流,Socket输入输出流
通过前几期的文章大家对channel也已经有所了解了。简单总结一下两者的区别:
阻塞API,channel同时支持阻塞、非阻塞API,并且 网络channel可以配合selector实现多路复用读写可以同时进行⚠️注意:
这里有一个误解,stream是单向的,channel是双向的。所以stream的读写可能会相互影响,这是不对的。 在网络编程里无论是stream还是channel都是全双工的。
接下来给大家出一个问题,相信大家有的指定遇到过。请问 同步阻塞、同步非阻塞、同步多路复用、异步阻塞(没有这种情况)、异步非阻塞这几个概念都是什么?相信大家一看到这几个词,不由得头一大,脑袋一懵,这是什么鬼。首先想要了解这些概念性质的东西,需要从IO模型上进行出发。
IO模型一共有5种:
这里参考书籍
Unix网络编程 -卷1

讲解概念之前先给大家看一张图

该图主要包含两个部分
当调用一次 channel.read 或 stream.read 后,会切换至操作系统内核态来完成真正数据读取,而读取又分为两个阶段,分别为:
同步的)
就是用户在读取数据期间什么也做不了,这就是
阻塞IO
同步的)
用户在读取数据的时候,如果没有数据会直接立刻返回,这个期间用户线程始终在运行并没有停止 ,这种情况我们称之为
非阻塞IO;但是当用户线程发现用数据了,它就不会立刻返回了,它需要完成第二阶段
复制数据的操作, 其实在复制数据的过程中,用户线程还是阻塞的。简单来说,就是在等待数据的过程中是非阻塞的,在复制数据的时候也是阻塞的
其实这种非阻塞IO并没有什么特别好的提升,它牵扯到了用户程序空间和Linux内核空间的多次切换。切换的太频繁反而会影响系统的性能。
本质上也是同步的)
这个情况和以上两种都不一样,它一上来不会去调用
read方法,而是去调用select,它会阻塞住,看有没有事件,一旦有事件,内核会告诉它有事件发生了,然后用户就可以根据selectorkey去拿到channel,然后调用read,在read期间,一旦复制数据,它还是会阻塞。

简单来说一下就是阻塞IO在与channel2 accpet建立连接的时候,如果channel1再次发来数据,阻塞IO是无法接受channel发送的数据的,它必须要等与channel2的连接建立完成后才可以。

如图所示,多路复用最大的好处就是: select可以检测多个channel上的事件,select方法执行之后它就在等待这些事件的发生,无论什么事件都会出发select向下运行,如果channel1的read事件和channe2的accept事件同时发生,那么select等待结束返回多个事件。
总结一句话就是
多路复用可以一次性的把多个channel上的事件都可以进行处理
关于网络IO模型的概念暂时就说这么多,后续持续更新