一举拿下网络 IO 模型

沙海 2021年6月12日06:05:14Java评论34字数 3400阅读11分20秒阅读模式
摘要

智能摘要

智能摘要文章源自JAVA秀-https://www.javaxiu.com/31436.html

在Linux,默认情况下所有的socket都是阻塞的,一个典型的读操作流程如图所示。当系统内核一直等到数据准备好了,它就会将数据从系统内核中拷贝到用户内存中,然后系统内核返回结果,用户进程才解除阻塞的状态,重新运行起来。当用户进程发出read操作时,如果内核中的数据还没有准备好,那么它并不会block用户进程,而是立刻返回一个错误。一旦内核中的数据准备好了,并且又再次收到了用户进程的系统调用,那么它马上就将数据复制到了用户内存中,然后返回正确的返回值。文章源自JAVA秀-https://www.javaxiu.com/31436.html

原文约 2747 | 图片 8 | 建议阅读 6 分钟 | 评价反馈文章源自JAVA秀-https://www.javaxiu.com/31436.html

一举拿下网络 IO 模型

程序IT圈 文章源自JAVA秀-https://www.javaxiu.com/31436.html

以下文章来源于盼盼编程,作者盼盼编程文章源自JAVA秀-https://www.javaxiu.com/31436.html

文章源自JAVA秀-https://www.javaxiu.com/31436.html

一举拿下网络 IO 模型文章源自JAVA秀-https://www.javaxiu.com/31436.html

盼盼编程文章源自JAVA秀-https://www.javaxiu.com/31436.html

CSDN top30,原创文章1000+, 资深/Golang/C++开发,现就职于知名互联网大厂。本号分享后台开发技术,包括算法与数据结构,笔试/面试,网络编程,数据库理论,操作系统,IT杂文文章源自JAVA秀-https://www.javaxiu.com/31436.html

文章源自JAVA秀-https://www.javaxiu.com/31436.html

前言

IO 是计算机体系中重要的一部分 。不同的 IO 设备有着不同的特点:数据率不一样、传送单位不一样,数据表示不一样,等等。所以,很难实现一种统一的输入输出方法。文章源自JAVA秀-https://www.javaxiu.com/31436.html

IO 有两种操作,同步 IO 和异步 IO。同步 IO 指的是,必须等待 IO 操作完成后,控制权才返回给用户进程。异步 IO 是,无须等待 IO 操作完成,就将控制权返回给用户进程。文章源自JAVA秀-https://www.javaxiu.com/31436.html

一举拿下网络 IO 模型文章源自JAVA秀-https://www.javaxiu.com/31436.html

上面就是一个典型的阻塞 IO,对方还没有准备好回啥,发送只能等着,知道对方想好回复语,再进行回复。下面学习一下常见的 4 种 IO 模型。文章源自JAVA秀-https://www.javaxiu.com/31436.html

阻塞 IO 模型文章源自JAVA秀-https://www.javaxiu.com/31436.html

在Linux ,默认情况下所有的 socket 都是阻塞的,一个典型的读操作流程如图所示。文章源自JAVA秀-https://www.javaxiu.com/31436.html

一举拿下网络 IO 模型文章源自JAVA秀-https://www.javaxiu.com/31436.html

阻塞和非阻塞的概念描述的是用户线程调用内核 IO 操作的方式:阻塞是指 IO 操作需要彻底完成后才返回到用户空间;而非阻塞是指 IO 操作被调用后立即返回给用户一个状态值,不需要等到 IO 操作彻底完成。文章源自JAVA秀-https://www.javaxiu.com/31436.html

当应用进程调用了 recvfrom 这个系统调用后,系统内核就开始了 IO 的第一个阶段 :准备数据。对于网络 IO 来说,很多时候数据在一开始还没到达时,系统内核就要等待足够的数据到来。而在用户进程这边,整个进程会被阻塞。当系统内核一直等到数据准备好了,它就会将数据从系统内核中拷贝到用户内存中,然后系统内核返回结果,用户进程才解除阻塞的状态,重新运行起来。所以,阻塞 IO 模型的特点就是 IO 执行的两个阶段都被阻塞了。文章源自JAVA秀-https://www.javaxiu.com/31436.html

大部分的 socke 接口都是阻塞型的。所谓阻塞型接口是指系统调用时却不返回调用结果,并让当前线程一直处于阻塞状态,只有当该系统调用获得结果或者超时出错时才返回结果。实际上,除非特别指定,几乎所有的 IO 接口都阻塞型的。这给网络编程带来了一个很大的问题,如在调用 send 的同时,线程处于阻塞状态,则在此期间,线程将无法执行任何运算或响应任何网络请求。文章源自JAVA秀-https://www.javaxiu.com/31436.html

文章源自JAVA秀-https://www.javaxiu.com/31436.html

非阻塞 IO 模型

在Linux 下,可以通过设置 socket IO 变为非阻塞状态。当一个非阻塞的 socket执行 read 操作时,流程如图:文章源自JAVA秀-https://www.javaxiu.com/31436.html

一举拿下网络 IO 模型文章源自JAVA秀-https://www.javaxiu.com/31436.html

当用户进程发出 read 操作时,如果内核中的数据还没有准备好,那么它并不会 block 用户进程,而是立刻返回一个错误。从用户进程角度讲,它发起 read 操作后,并不需要等待,而是马上就得到了一个结果 当用户进程判断结果是一个错误时,它就知道数据还没有准备好,于是它可以再次发送 read 操作。一旦内核中的数据准备好了,并且又再次收到了用户进程的系统调用,那么它马上就将数据复制到了用户内存中,然后返回正确的返回值。文章源自JAVA秀-https://www.javaxiu.com/31436.html

所以,在非阻塞式 IO 中,用户进程其实需要不断地主动询问 kernel 数据是否准备好。非阻塞的接口相比于阻塞型接口的显著差异在于被调用之后立即返回,使用如下的函数可以将某句柄归设为非阻塞状态:fcntl( fd , F_SETFL , O_NONBLOCK);文章源自JAVA秀-https://www.javaxiu.com/31436.html

在非阻塞状态下,recv 接口在被调用后立即返回,返回值代表了不同的含义,如下所述。文章源自JAVA秀-https://www.javaxiu.com/31436.html

  • recv 返回值大于 0,表示接收数据完毕,返回值即是接收到的字节数。文章源自JAVA秀-https://www.javaxiu.com/31436.html

  • recv 返回 0,表示连接已经正常断开。文章源自JAVA秀-https://www.javaxiu.com/31436.html

  • recv 返回 -1 ,且 errno 等于 EAGAIN ,表示 recv 操作还没执行完成。文章源自JAVA秀-https://www.javaxiu.com/31436.html

  • recv 返回 -1,且 errno 不等于 EAGAIN ,表示 recv 操作遇到系统错误 errno。文章源自JAVA秀-https://www.javaxiu.com/31436.html

可以看到服务器线程可以通过循环调用 recv 接口,可以在单个线程内实现对所有连接的数据接收。但是上述模型绝不被推荐,因为循环调用 recv 将大幅度占用 CPU 使用率。此外,在这个方案 recv 更多的是起到检测“操作是否完成”的作用,实际操作系统提供了更为高效的检测“操作是否完成”作用的接口,例如 select 多路复用模式,可以次检测多个连接是存活跃。文章源自JAVA秀-https://www.javaxiu.com/31436.html

多路 IO 复用模型

多路 IO 复用,有时也称为事件驱动 IO。它的基本原理就是有个函数会不断地轮询所负责的所有 socket ,当某个 socket 有数据到达了,就通知用户进程。IO 复用模型的流程如图:文章源自JAVA秀-https://www.javaxiu.com/31436.html

一举拿下网络 IO 模型文章源自JAVA秀-https://www.javaxiu.com/31436.html

当用户进程调用了 select ,那么整个进程会被阻塞,而同时,内核会 "监视" 所有 select 负责的 socket ,当任何一个 socket 中的数据准备好了, select 就会返回。这个时候用户进程再调用 read 操作,将数据从内核拷贝到用户进程。文章源自JAVA秀-https://www.javaxiu.com/31436.html

这个模型和阻塞 IO 的模型其实并没有太大的不同,事实上还更差一些 因为这里需要使用两个系统调用,而阻塞 IO 只调用了一个系统调用 recvfrom,用 select 的优势在于它可以同时处理多个连接文章源自JAVA秀-https://www.javaxiu.com/31436.html

如果处理的连接数不是很高的话,使用 select/epoll Web server 定比使用多线程的阻塞 IO Web server 性能更好,可能延迟还更大;select/poll 的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接文章源自JAVA秀-https://www.javaxiu.com/31436.html

异步 IO 模型

一举拿下网络 IO 模型文章源自JAVA秀-https://www.javaxiu.com/31436.html

上面是异步 IO 模型。文章源自JAVA秀-https://www.javaxiu.com/31436.html

用户进程发起 read 操作之后,立刻就可以开始去做其他的事;而另一方面,从内核的角度,当它收到一个异步的 read 请求操作之后,首先会立刻返回,所以不会对用户进程产生任何阻塞。然后,内核会等待数据准备完成,然后将数据拷贝到用户内存中,当这一切都完成之后,内核会给用户进程发送一个信号,返回 read 操作已完成的信息。文章源自JAVA秀-https://www.javaxiu.com/31436.html

调用阻塞 IO 一直阻塞住对应的进程直到操作完成,而非阻塞 IO 在内核还在准备数据的情况下会立刻返回。两者的区别就在于同步 IO 进行 IO 操作时会阻塞进程。非阻塞 IO 在执行 recvfrom 这个系统调用的时候,如果内核的数据没有准备好,这时候不会阻塞进程。但是当内核中数据准备好时,recvfrom 会将数据从内核拷贝到用户内存中,这个时候进程则被阻塞。而异步 IO 则不 样,当进程发起 IO 操作之后,就直接返回,直到内核发送一个信号,告诉进程 IO 已完成,则在这整个过程中,进程完全没有被阻塞文章源自JAVA秀-https://www.javaxiu.com/31436.html

絮叨

经过上面的学习,你会发现非阻塞 IO 和异步 IO 的区别还是很明显的。在非阻塞 IO 中,虽然进程大部分时间都不会被阻塞,但是它仍然要求进程去主动检查,并且当数据准备完成以后,也需要进程主动地再次调用 recvfrom 来将数据拷贝到用户内存中。而异步IO 则完全不同,它就像是用户进程将整个 IO 操作交给了内核完成,然后内核做完后发信号通知。文章源自JAVA秀-https://www.javaxiu.com/31436.html

文章源自JAVA秀-https://www.javaxiu.com/31436.html

IO 作为计算机的基础知识,后台开发务必要掌握。更多网络编程相关的知识可以去学习 unix 网络编程,祝大家学习愉快!文章源自JAVA秀-https://www.javaxiu.com/31436.html

文章源自JAVA秀-https://www.javaxiu.com/31436.html

················· END ··················文章源自JAVA秀-https://www.javaxiu.com/31436.html

最后给大家送下福利,大家可以关注Java后端编程公众号,在后台回复 “Java”可以获取一份我整理的最新Java面试题资料。文章源自JAVA秀-https://www.javaxiu.com/31436.html

-END-PS:欢迎在留言区留下你的观点,一起讨论提高。如果今天的文章让你有新的启发,欢迎转发分享给更多人。Java后端编程交流群已成立公众号运营至今,离不开小伙伴们的支持。为了给小伙伴们提供一个互相交流的平台,特地开通了官方交流群。扫描下方二维码备注 进群 或者关注公众号 Java后端编程 后获取进群通道。

—————END—————文章源自JAVA秀-https://www.javaxiu.com/31436.html

推荐阅读:Spring Boot 实战:打造属于自己的私人云盘适合 Spring Boot 初学者的 OA 开源项目再见!收费的 XShell,我改用这款国产良心工具!一个帮你轻松搞定第三方登陆的 Java 开源组件最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:关注公众号并回复 java 领取,更多内容陆续奉上。
文章源自JAVA秀-https://www.javaxiu.com/31436.html

明天见(。・ω・。)ノ♡文章源自JAVA秀-https://www.javaxiu.com/31436.html

继续阅读
速蛙云 - 极致体验,强烈推荐!!!购买套餐就免费送各大视频网站会员!快速稳定、独家福利社、流媒体稳定解锁!速度快,全球上网、视频、游戏加速、独立IP均支持!基础套餐性价比很高!这里不多说,我一直正在使用,推荐购买:https://www.javaxiu.com/59919.html
weinxin
资源分享QQ群
本站是JAVA秀团队的技术分享社区, 会经常分享资源和教程; 分享的时代, 请别再沉默!
沙海
  • 版权声明:本站是JAVA秀团队的技术分享社区,我们会经常分享资源和教程。
  • 转载请注明:一举拿下网络 IO 模型 - JAVA秀 ☜(ˆ▽ˆ)
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定