网络编程实战
盛延敏
前大众点评云平台首席架构师
44207 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 40 讲
网络编程实战
15
15
1.0x
00:00/00:00
登录|注册

22 | 非阻塞I/O:提升性能的加速器

非阻塞TCP套接字上的connect函数
非阻塞情况下的监听套接字
非阻塞情况下的write函数
非阻塞情况下的read调用
书店购书例子
书店购书例子
第二道思考题
第一道思考题
非阻塞I/O与I/O多路复用技术的搭配使用
非阻塞I/O的使用场景
例子代码
connect
accept
写操作
读操作
非阻塞I/O
阻塞I/O
思考题
总结
非阻塞I/O + select多路复用
非阻塞I/O
阻塞 VS 非阻塞
非阻塞I/O

该思维导图由 AI 生成,仅供参考

你好,我是盛延敏,这里是网络编程实战第 22 讲,欢迎回来。
在性能篇的前两讲中,我分别介绍了 select 和 poll 两种不同的 I/O 多路复用技术。在接下来的这一讲中,我将带大家进入非阻塞 I/O 模式的世界。事实上,非阻塞 I/O 配合 I/O 多路复用,是高性能网络编程中的常见技术。

阻塞 VS 非阻塞

当应用程序调用阻塞 I/O 完成某个操作时,应用程序会被挂起,等待内核完成操作,感觉上应用程序像是被“阻塞”了一样。实际上,内核所做的事情是将 CPU 时间切换给其他有需要的进程,网络应用程序在这种情况下就会得不到 CPU 时间做该做的事情。
非阻塞 I/O 则不然,当应用程序调用非阻塞 I/O 完成某个操作时,内核立即返回,不会把 CPU 时间切换给其他进程,应用程序在返回后,可以得到足够的 CPU 时间继续完成其他事情。
如果拿去书店买书举例子,阻塞 I/O 对应什么场景呢? 你去了书店,告诉老板(内核)你想要某本书,然后你就一直在那里等着,直到书店老板翻箱倒柜找到你想要的书,有可能还要帮你联系全城其它分店。注意,这个过程中你一直滞留在书店等待老板的回复,好像在书店老板这里"阻塞"住了。
那么非阻塞 I/O 呢?你去了书店,问老板有没你心仪的那本书,老板查了下电脑,告诉你没有,你就悻悻离开了。一周以后,你又来这个书店,再问这个老板,老板一查,有了,于是你买了这本书。注意,这个过程中,你没有被阻塞,而是在不断轮询。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

非阻塞I/O技术在网络编程中具有重要应用价值。相较于阻塞I/O,非阻塞I/O能够提升性能,并且在应用程序调用完成后立即返回,不会挂起应用程序,从而提高CPU利用率。结合I/O多路复用技术,非阻塞I/O成为高性能网络编程中常见的技术。在非阻塞I/O模式下,需要小心处理读操作立即返回的错误信息,以及尽可能拷贝数据到发送缓冲区中的写操作。此外,将监听套接字设置为非阻塞可以避免极端情况下的阻塞问题。非阻塞TCP套接字上调用connect函数会立即返回连接状态,可以通过I/O多路复用进行检测。文章中提供了一个非阻塞I/O搭配select多路复用的例子,展示了非阻塞I/O的实际应用。总之,非阻塞I/O技术在网络编程中具有重要意义,能够提升性能,值得开发者深入学习和应用。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《网络编程实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(67)

  • 最新
  • 精选
  • HerofH
    老师您好!我看到您这在应用层设计了一个读写缓冲区,我之前看了muduo和libevent,也是设计了这样的缓冲区,并且muduo作者陈硕也提到非阻塞IO必须要设计一个应用层Buffer,我很疑惑的就是,这样的读写缓冲区的必要性是什么呢? 我大概只能理解到非阻塞IO下使用应用层写缓冲区可以让还未来得及发出的数据先保存在应用层Buffer中,然后等到可写的时候再将数据从应用层Buffer写到fd的发送缓冲区中; 那么如何理解应用层读缓冲区的必要性呢?有数据来,触发可读事件,这个时候直接调用read去读不就可以了吗,为什么一定要先读到读缓冲区呢?根据libevent中,每次读数据时都会尽量多的从fd的接收缓冲区中读取数据到应用层buffer,我的一种想法是,设置读缓冲区的作用,是否是为了减少read的调用次数呢? 还是有其它原因呢?想了解一下老师的看法,谢谢!

    作者回复: 读缓冲的作用有很多,你提到了通过设置缓冲区,减少系统调用的次数是一个方面,另外,别忘了读取的数据是需要在应用层进行报文解析的,一个应用层缓冲区显然是比较方便的,否则,需要不断的进行数据的读取,直至解析到完整的报文。我认为,应用层缓冲是"空间换时间"的一个比较好的例子。

    2020-01-14
    38
  • TinyCalf
    我在思考一个问题,select既然已经告诉我们接口可读了,为什么还要用非阻塞IO;我自己的想法是,select其实只通知了有没有内容可读,没有提供有多少数据可读,所以当我们使用阻塞IO循环read时,无法确认下一个read还是不是可读的,因此仍然可能阻塞,而非阻塞IO可以解决这个问题,不知道我想的对不对

    作者回复: 我觉得是可以这样理解的。

    2020-11-08
    2
    16
  • 衬衫的价格是19美元
    1.select,poll,epoll是io多路复用技术,是操作系统提供的检测io事件是否就绪的方法,当然我们可以不用操作系统提供的方法而自己去写一个轮训,但是轮训会加重cpu负载。 2.当我们调用fcntl将套接字配置为非阻塞后,在该套接字上后续的accept,read,write操作都将变为非阻塞 3.非阻塞io一般都需要配合io多路复用技术使用

    作者回复: 总结到位👍

    2020-07-12
    3
    12
  • MoonGod
    感觉这篇的解释和前面的比起来太不细致了…很多地方都没说明。老师能不能多一些说明啊

    作者回复: 我在代码里多加一些注释,可以看最新的代码 https://github.com/froghui/yolanda

    2019-09-27
    4
    12
  • 扩散性百万咸面包
    老师,认真的问你一个问题。 Redis中,网上的介绍是说单线程 + 多路复用 + 非阻塞I/O。为什么不采取C10k问题中的,主从Reactor结构,多个事件分发器来充分利用CPU的多核能力呢?理论上这样更好啊。

    作者回复: 很认真的回答你,我觉得你说的 单线程 + 多路复用 + 非阻塞I/O,是和redis的设计有关的,通过这么一个设计,减少了多个线程锁的消耗,我想是redis做了一些取舍的。

    2020-06-06
    2
    10
  • fedwing
    那么非阻塞 I/O 呢?你去了书店,问老板有没你心仪的那本书,老板查了下电脑,告诉你没有,你就悻悻离开了。一周以后,你又来这个书店,再问这个老板,老板一查,有了,于是你买了这本书。注意,这个过程中,你没有被阻塞,而是在不断轮询。但轮询的效率太低了,于是你向老板提议:“老板,到货给我打电话吧,我再来付钱取书。”这就是前面讲到的 I/O 多路复用。 对于这个我有点疑问,select和poll本质上,不都是轮询吗,为什么这里说轮询效率太低,改成select,poll

    作者回复: select和poll是"老板"这个内核自己在轮询哦,不是买书人(应用程序)在轮询,"老板"可以有多个方式优化这个过程,比如他记录了一个事件,一旦书定成了,他就发现需要告诉和他有订阅关系的"你"了。想想看,作为应用程序的"你"在这个过程中,是不是可以放开手干点别的事,比如玩个吃鸡游戏的什么。

    2020-08-13
    4
    9
  • YUAN
    select和poll也是轮训吧😄?

    作者回复: 我把它归为多路复用。轮询的意思是应用程序自己不断的从应用层发起检测。

    2020-10-03
    6
  • javaYJL
    老师,accept()这个函数不是阻塞的吗?

    作者回复: accept和阻塞套接字一起使用就是阻塞的,和非阻塞套集字一起使用就是非阻塞的。阻塞和非阻塞是作用到套集字上的。

    2019-11-05
    6
  • 绿箭侠
    老师,评论区中 程序水果宝 说select非阻塞,我的理解:select(maxfd + 1, &readset, &writeset, &exset, NULL) 此处因为NULL当然阻塞,不明白为什么说select非阻塞??

    作者回复: 非阻塞和阻塞是指I/O,具体作用到的是套接字上,而select这里是I/O多路复用的一种技术,注意到这一行 : make_nonblocking(fd); 实际上是把套接字都改为非阻塞I/O,再通过I/O多路复用来接收套接字上的I/O事件。

    2020-02-28
    3
    5
  • 一天到晚游泳的鱼
    老师,我想请教一个问题就是, 当把一个描述符设置为非阻塞的之后,在该描述符上面的操作就会变成非阻塞的吗? 比如说把连接套接字设置为非阻塞的,send和recv就会变成非阻塞的吗?

    作者回复: 你的理解是对的。

    2019-10-05
    2
    5
收起评论
显示
设置
留言
67
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部