网络编程实战
盛延敏
前大众点评云平台首席架构师
立即订阅
6034 人已学习
课程目录
已完结 39 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 学好网络编程,需要掌握哪些核心问题?
免费
第一模块:基础篇 (9讲)
01 | 追古溯源:TCP/IP和Linux是如何改变世界的?
02 | 网络编程模型:认识客户端-服务器网络模型的基本概念
03丨套接字和地址:像电话和电话号码一样理解它们
04 | TCP三次握手:怎么使用套接字格式建立连接?
05 | 使用套接字进行读写:开始交流吧
06 | 嗨,别忘了UDP这个小兄弟
07 | What? 还有本地套接字?
08 | 工欲善其事必先利其器:学会使用各种工具
09丨答疑篇:学习网络编程前,需要准备哪些东西?
第二模块:提高篇 (10讲)
10 | TIME_WAIT:隐藏在细节下的魔鬼
11 | 优雅地关闭还是粗暴地关闭 ?
12 | 连接无效:使用Keep-Alive还是应用心跳来检测?
13 | 小数据包应对之策:理解TCP协议中的动态数据传输
14丨UDP也可以是“已连接”?
15 | 怎么老是出现“地址已经被使用”?
16 | 如何理解TCP的“流”?
17 | TCP并不总是“可靠”的?
18 | 防人之心不可无:检查数据的有效性
19丨提高篇答疑:如何理解TCP四次挥手?
期中复习周 (2讲)
期中大作业丨动手编写一个自己的程序吧!
免费
期中大作业丨题目以及解答剖析
免费
第三模块:性能篇 (12讲)
20 | 大名⿍⿍的select:看我如何同时感知多个I/O事件
21 | poll:另一种I/O多路复用
22 | 非阻塞I/O:提升性能的加速器
23 | Linux利器:epoll的前世今生
24 | C10K问题:高并发模型设计
25 | 使用阻塞I/O和进程模型:最传统的方式
26 | 使用阻塞I/O和线程模型:换一种轻量的方式
27 | I/O多路复用遇上线程:使用poll单线程处理所有I/O事件
28 | I/O多路复用进阶:子线程使用poll处理连接I/O事件
29 | 渐入佳境:使用epoll和多线程模型
30 | 真正的大杀器:异步I/O探索
31丨性能篇答疑:epoll源码深度剖析
第四模块:实战篇 (4讲)
32 | 自己动手写高性能HTTP服务器(一):设计和思路
33 | 自己动手写高性能HTTP服务器(二):I/O模型和多线程模型实现
34 | 自己动手写高性能HTTP服务器(三):TCP字节流处理和HTTP协议实现
35 | 答疑:编写高性能网络编程框架时,都需要注意哪些问题?
结束语 (1讲)
结束语丨我相信这不是结束,让我们江湖再见
网络编程实战
登录|注册

30 | 真正的大杀器:异步I/O探索

盛延敏 2019-10-16
你好,我是盛延敏,这里是网络编程实战的第 30 讲,欢迎回来。
在性能篇的前几讲中,我们谈到了阻塞 I/O、非阻塞 I/O 以及像 select、poll、epoll 等 I/O 多路复用技术,并在此基础上结合线程技术,实现了以事件分发为核心的 reactor 反应堆模式。你或许还听说过一个叫做 Proactor 的网络事件驱动模式,这个 Proactor 模式和 reactor 模式到底有什么区别和联系呢?在今天的内容中,我们先讲述异步 I/O,再一起揭开以异步 I/O 为基础的 proactor 模式的面纱。

阻塞 / 非阻塞 VS 同步 / 异步

尽管在前面的课程中,多少都涉及到了阻塞、非阻塞、同步、异步的概念,但为了避免看见这些概念一头雾水,今天,我们就先来梳理一下这几个概念。
第一种是阻塞 I/O。阻塞 I/O 发起的 read 请求,线程会被挂起,一直等到内核数据准备好,并把数据从内核区域拷贝到应用程序的缓冲区中,当拷贝过程完成,read 请求调用才返回。接下来,应用程序就可以对缓冲区的数据进行数据解析。
第二种是非阻塞 I/O。非阻塞的 read 请求在数据未准备好的情况下立即返回,应用程序可以不断轮询内核,直到数据准备好,内核将数据拷贝到应用程序缓冲,并完成这次 read 调用。注意,这里最后一次 read 调用,获取数据的过程,是一个同步的过程。这里的同步指的是内核区域的数据拷贝到缓存区这个过程。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《网络编程实战》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(17)

  • fackgc17
    Linux 的 AIO 机制可能后面逐渐不用了,可以关注 5.1 的 io_uring 机制,大杀器

    作者回复: 赞,学习了。

    2019-10-16
    3
  • 传说中的成大大
    看第二遍理解了reactor和proactor的区别前者是同步 有消息到达时调用应用程序的回调,应用程序自己调用read 同步取得数据,而后者是内核异步数据读取完成之后才调用应用程序的回调

    作者回复: 我理解Linux下标榜的proactor其实都是伪的。

    2019-10-16
    2
  • godtrue
    记一下自己对阻塞/非阻塞/同步/异步的理解
    1:阻塞/非阻塞——是站在调用者(客户端或请求方)的角度来说的,如果调用者要数据,此时服务者没准备好,调用者不用傻等,那就是非阻塞的,否则就是阻塞的

    2:同步/异步——是站在服务者(服务端或响应端)的角度来说的,如果服务者不会主动给请求者它想要的数据,那就是同步的,否则就是异步的

    3:两个位置每个位置有两种状态,总共四种状态——同步阻塞/同步非阻塞/异步阻塞(不搭)/异步非阻塞
    ,其中同步阻塞和异步非阻塞是很搭的相互成就,异步阻塞是非常不搭的相互矛盾,同步非阻塞有一点怪,它通常就是靠不断的轮询来实现的,服务者不会主动把准备好的数据发给调用者,调用者也不会等着服务者把数据准备好再返回。

    4:导致出现这种现象的根本原因,我觉得是数据的读取是一个慢动作,数据不管从磁盘中拿出来还是放入到磁盘中,相对内存操作相对CPU执行命令的操作速度是非常慢的,这种速度差必然导致要么等一等,要么不断的来瞧瞧,要么准备好了送过去,这三种解决此问题的思路。
    2019-12-01
  • 土豆牛肉
    既然Windows有iocp,是不是可以说Windows更适合运行网络服务器呢

    作者回复: 不是哦,只是设计上各有千秋,现在互联网上跑的最多的还是Linux,就连微软,也在积极拥抱Linux。

    2019-11-20
  • 夏目
    老师,可以把阻塞非阻塞对应数据准备过程,同步异步对应数据从内核到应用程序缓冲区过程吗?

    作者回复: 你这样理解也可以。

    2019-11-18
  • 马不停蹄
    异步I/O就相当于当数据真正到达或者说应用程序读取完数据了通过注册的回调函数通知你去处理,用 netty 是这样的,但是老师有个问题一直不明白:netty 并没有用异步I/O,而是基于(多路复用+非阻塞I/O)+ Future 实现了异步非阻塞吗?

    作者回复: Netty用的就是epoll,基于多路复用+非阻塞I/O,至于Future,只是Java里包装异步调用的一种方式,并不是真正的异步 I/O。

    2019-11-13
  • 传说中的成大大
    issue和mr是啥意思啊,没接触到过呢!

    作者回复: issue是提一个问题到github上,mr是看哪里有问题直接改代码,提一个merge request过来,我直接merge到master把问题解决了

    2019-10-19
  • Steiner
    应该这么说吧,同步和异步是指数据准备过程,阻塞非阻塞是数据获取过程

    作者回复: 也可以这么说吧。

    2019-10-18
  • 传说中的成大大
    在poll-server-onethread程序中 onMessage回调里面调用 char *run_cmd(char *cmd) {
        char *data = malloc(16384);
        bzero(data, sizeof(data));
        FILE *fdp;
        const int max_buffer = 256;
        char buffer[max_buffer];
        fdp = popen(cmd, "r");
        char *data_index = data;
        if (fdp) {
            while (!feof(fdp)) {
                if (fgets(buffer, max_buffer, fdp) != NULL) {
                    int len = strlen(buffer);
                    memcpy(data_index, buffer, len);
                    data_index += len;
                }
            }
            pclose(fdp);
        }
        return data;
    }
    总是提示 get message from tcp connection connection-7
    ls
    : not found
    这就让我很蛋疼了,百度了半天没解决到

    作者回复: 从onMessage如何调到run_cmd的?

    2019-10-17
    1
  • 传说中的成大大
    我把github上的代码进行了改进,收到消息时执行run_cmd 用来实现ls pwd ...的shell命令,但是总是提示: not found 原谅我抄的代码,只是对代码进行了逻辑修改 ,百度了半天都解决不了这个问题

    作者回复: 贴你的代码过来,大家一起会诊。

    2019-10-17
  • 沉淀的梦想
    Proactor中所谓的队列,我的理解是一个Block Queue,给aio注册一个回调函数,回调函数的内容是往BlockQueue中放置一个通知,然后event loop线程苏醒,获取到这个通知后进行分发,不知道理解的对不对?

    还有一个疑问POSIX的aio库要怎么注册回调?Java里面的aio有这个功能,感觉linux也应该提供吧

    作者回复: Java是一个跨OS的语言,AIO的实施需充分调用OS参与,我理解可能对windows支持的比较好,Linux支持的一般吧。

    2019-10-17
  • 阿卡牛
    还有比异步IO更好的吗?

    作者回复: 我知道的这个已经把该办的事情都办了。

    2019-10-16
  • 传说中的成大大
    我也想知道应该怎么取设计和封装接口函数 类等等
    2019-10-16
  • 传说中的成大大
    老师 你好 我要怎么样才能像你一样设计一个服务器框架呢?我需要哪些知识储备呢?

    作者回复: 把我的代码看懂,然后搞清楚原理,自己试着慢慢撸一个。

    2019-10-16
  • 程序水果宝
    看了最近几篇文章以后个人感觉应该把反应堆、epoll、异步和同步的函数列出来配合着它们的功能讲,很有可能不懂的地方都在那些封装的函数里面,像main函数里面的内容反而给出链接加注释就可以了,这样可能会让人的理解更加深刻一些。还有实验结果也不用列这么多,这些完全可以由自己去实验。

    作者回复: 感谢你的建议。时间有限,做出来的内容可能没有办法满足所有人的需求。在第四篇里可能会解答你的大部分疑惑,如果有进一步的问题,我可以在答疑中统一回复,解答大家的疑惑。

    2019-10-16
  • 传说中的成大大
    而突然又理解到了同步i/o和异步i/o的问题 比如我调用read函数 在read函数返回之前数据被拷贝到缓冲区这个过程就是同步i/o的操作 像后面的aio系列函数 是在函数调用后 内核把数据拷贝到应用层缓冲区 这个就叫异步

    作者回复: 你真的悟道了,哈哈:)

    2019-10-16
  • 传说中的成大大
    再第二遍读的时候 我突然理清了 阻塞/非阻塞 io 和同步/异步io 这里提到的都是跟i/o操作相关 我又想起了线程的同步和异步 跟阻塞和阻塞 没有半毛钱的关系啊。。。。。

    作者回复: 好像有点悟道的意思.....

    2019-10-16
收起评论
17
返回
顶部