为什么IO多路复用要搭配非阻塞IO?

发布于 2022-09-01 20:43:47 字数 302 浏览 22 评论 0

IO多路复用的函数是阻塞的 比如 select();

当有套接口可读时, select函数就返回了, 告诉我们套接口已经可读, 然后我们去读这个套接口, 可以用阻塞的read或者非阻塞的read, 阻塞函数是无数据可读就阻塞进程, 非阻塞函数是无数据可读就返回一个EWOULDBLOCK错误. 那么问题来了: select都返回可读了, 那就表示一定能读了. 阻塞函数read也能读取了也就不会阻塞了, 非阻塞函数也有数据读了,也不会返回错误了. 那么这俩不都一样了? 为什么还得用非阻塞函数? 还有Reactor模式也是用的IO多路复用与非阻塞函数, 这是什么道理呢?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

山川志 2022-09-08 20:43:47

IO和NIO的关键就在你读取的过程中,假设一个情况,你正在读取一个数据,它的长度是500字节,但是目前传输而来的数据只有200字节,还有300在路上。这时候你有两种方式,一种是继续阻塞,等待那些数据到达。不过这显然不是个好方法,因为你不知道那些数据还有多久到达(有可能网络中断了,它们永远不会到达了)。另外一种方法是将已经读取的数据先记录到缓冲中,然后继续等待运行(一般就是再等待接口可读),等数据到达了再拼接起来。而NIO就是帮你搭建了第二种方法的基础,帮你把缓冲等问题处理好了,这样虽然两个读取都是阻塞的,但是第一种阻塞是网络IO的阻塞,第二种阻塞是本地缓冲IO的阻塞,显然第二种更有确定性、更可靠。特别实在读取数据到下一次等等套接字可读的过程中,你还需要做一些其他的响应或处理时,这个线程就要保障不能长时间阻塞,所以NIO是个很好的解决办法。

总的来说NIO只是在BIO上做一个简单封装,让你专注到实现功能中去,不用再考虑网络IO阻塞的问题。

颜漓半夏 2022-09-08 20:43:47

搭配非阻塞是为了提高应用的响应速度,select一样可以阻塞调用,Reactor非阻塞是他自己的架构设计。。另外read阻塞不阻塞取决于socket本身。

独孤求败 2022-09-08 20:43:47

举两个例子:

客户端发送连接请求
服务器通过select发现监听套接字可读
客户端发送RST中断连接
服务器调用阻塞式accpet并被阻塞(Berkeley内核不会将连接中断的错误ECONNABORTED从accpet返回)

使用select检测到套接字可读后,由于一次读取操作可能不足以将所有数据取出。此时有两种做法:
1)使用非阻塞io不断读取直到遇到EWOULDBLOCK错误
2)读取一次后继续调用select,若检测到套接字仍可读,则重复读取操作
显然,方式1更为简洁高效

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文