往期文章简单讲解了Netty入门基础篇的相关基本概念:
网络编程之IO:说到IO不得不会想到NIO
和BIO
,说到这两个概念我们不得不看一下两个:
stream和channel
stream就是咱们以前接触的文件输入输出流,Socket输入输出流
通过前几期的文章大家对channel
也已经有所了解了。简单总结一下两者的区别:
-
stream不会自动缓冲数据,channel会利用系统提供的发送缓冲区,接受缓冲区(更为底层) -
stream仅支持 阻塞
API,channel同时支持阻塞
、非阻塞
API,并且 网络channel可以配合selector实现多路复用
-
两者均为全双工,即 读写
可以同时进行
⚠️注意:
这里有一个误解,stream是单向的,channel是双向的。所以stream的读写可能会相互影响,这是不对的。
在网络编程里无论是stream还是channel都是全双工的。
接下来给大家出一个问题,相信大家有的指定遇到过。请问 同步阻塞
、同步非阻塞
、同步多路复用
、异步阻塞
(没有这种情况)、异步非阻塞
这几个概念都是什么?相信大家一看到这几个词,不由得头一大,脑袋一懵,这是什么鬼。首先想要了解这些概念性质的东西,需要从IO模型上进行出发。
IO模型
IO模型一共有5种:
-
阻塞IO 2. 非阻塞IO 3. 多路复用 4. 信号驱动 5. 异步IO
这里参考书籍
Unix网络编程 -卷1
-
同步:线程自己去获取结果(一个线程) -
异步:线程自己不去获取结果,而是由其它线程送结果(至少两个线程)

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

该图主要包含两个部分
-
1.用户程度空间(相当于Java代码) 2. Linux内核空间 -
该图主要说的就是读取数据 本身Java代码是没有网络读取数据的功能的。它需要调用操作系统的内核空间去读取数据。也就是用户空间和系统内核空间的切换。
等待数据:等待client的数据发送过来 复制数据:将数据从网卡读取到内存中
当调用一次 channel.read
或 stream.read
后,会切换至操作系统内核态来完成真正数据读取,而读取又分为两个阶段,分别为:
-
等待数据阶段 -
复制数据阶段
-
什么是阻塞IO( 同步的
)

就是用户在读取数据期间什么也做不了,这就是
阻塞IO
-
什么是非阻塞IO( 同步的
)

用户在读取数据的时候,如果没有数据会直接立刻返回,这个期间用户线程始终在运行并没有停止 ,这种情况我们称之为
非阻塞IO
;
但是当用户线程发现用数据了,它就不会立刻返回了,它需要完成第二阶段
复制数据
的操作, 其实在复制数据的过程中,用户线程还是阻塞的。简单来说,就是在等待数据的过程中是非阻塞的,在复制数据的时候也是阻塞的
其实这种非阻塞IO
并没有什么特别好的提升,它牵扯到了用户程序空间和Linux内核空间的多次切换。切换的太频繁反而会影响系统的性能。
-
多路复用 ( 本质上也是同步的
)

这个情况和以上两种都不一样,它一上来不会去调用
read
方法,而是去调用select
,它会阻塞住,看有没有事件,一旦有事件,内核会告诉它有事件发生了,然后用户就可以根据selectorkey去拿到channel,然后调用read,在read期间,一旦复制数据,它还是会阻塞。
-
相信大家不难发现这个多路复用也是两次阻塞,这和阻塞IO有什么区别吗?
请大家查看这两张图:
简单来说一下就是阻塞IO在与channel2
accpet
建立连接的时候,如果channel1再次发来数据,阻塞IO是无法接受channel发送的数据的,它必须要等与channel2的连接建立完成后才可以。
如图所示,多路复用最大的好处就是:
select可以检测多个channel上的事件,select方法执行之后它就在等待这些事件的发生,无论什么事件都会出发select向下运行,如果channel1的read事件和channe2的accept事件同时发生,那么select等待结束返回多个事件。
总结一句话就是
多路复用
可以一次性
的把多个channel
上的事件都可以进行处理
关于网络IO模型的概念暂时就说这么多,后续持续更新
微信搜索【
码上遇见你
】获取更多精彩内容
原文始发于微信公众号(码上遇见你):Netty网络编程之IO模型
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/78756.html