这次 moon 要把网络 I/O 一网打尽

微号:moon聊技术

关注选择“ 星标 ”, 重磅干货,第一 时间送达!

[如果你觉得文章对你有帮助,欢迎关注,在看,点赞,转发]

[TOC]

前言

大家好,我是 moon,上一次和大家聊了一下 socket(这次 moon 要把 socket 玩的明明白白),相信大家对 socket 有了一定的认识,对于 socket 还不熟悉的同学,可以先看看 socket 这篇文章,今天这篇文章是基于 socket,再和大家讲一讲网络I/O相关的知识,也刚好为后续 netty 的文章做下铺垫

什么是 I/O ?

I:其实就是 Input,输入

O:其实就是 Output,输出

所以 I/O 很好理解,就是输入和输出

生活中最简单的例子,你用微信和别人聊天,你发送信息给对方,就是输入对方回给你信息,你接受到了,就是输出

一般情况下,在软件中我们常说的 I/O 是指网络 I/O 和磁盘 I/O,今天我们就来聊下网络 I/O

网络 I/O 又是什么?

其实网络 I/O 就是网络中的输入与输出,我们再说详细点,正常的网络通信中,一条消息发送的过程中有一个很重要的媒介,叫做网卡,它的作用有两个

  • 一是将电脑的数据封装为帧,并通过网线(对无线网络来说就是电磁波)将数据发送到网络上去
  • 二是接收网络上其它设备传过来的帧,并将帧重新组合成数据,发送到所在的电脑中。
image.png

网卡能接收所有在网络上传输的信号,但正常情况下只接受发送到该电脑的帧和广播帧,将其余的帧丢弃。

所以网络 I/O 其实网络与服务端(电脑内存)之间的输入与输出

为什么会有网络 I/O 模型?

一般情况下,一次网络数据的传输会从客户端发送给服务端,由服务端网卡接受,转交给内存,最后由 cpu 执行相应的业务操作

只要有一点电脑知识的读者大多数都知道,cpu、显卡、内存等电脑中你数得上名字的模块,运行效率最高的就是 cpu 了,所以为了整个网络传输的提效,就诞生出了五种网络 I/O 模型

当然还有一点原因

image.png

不管是客户端还是服务端,在发送和接受数据的时候,都是要与 socket 缓冲区去进行交互的,那么什么时候交互?是否需要等待响应?基于这些不同的业务场景,也就有了五种网络 I/O 模型

其实这个结论是通用的,任何模型的调优改造健全一般都是围绕着性能、安全、业务场景这三个方向来前进的

I/O 模型

image.png

好了,我们说完了 I/O 模型的诞生,就来具体的研究下具体是哪五种 I/O 模型

阻塞 I/O

image.png

阻塞 I/O,顾名思义,就是在各个状态完全阻塞住整个 I/O 过程是个串行化的,在数据传输开始时,都要等到后续的每一个操作完成后才可以继续,这也是 linux 系统默认的 I/O 模型,当然,这种模型的问题就是效率非常的低

第二个问题就是,如果是在生产环境多线程的情况下,会有频繁线程的上下文切换,而这个切换又是非常消耗资源的。

非阻塞 I/O

非阻塞 I/O 针对于阻塞 I/O 有了一些改进

image.png

在系统调用内核后,内核如果没有准备好数据,则直接会返回一个错误码,直到数据准备好后,再走后续的流程

中间会有一个一直定时去询问的动作,所以它的缺点也就是在这里,需要一直去处理数据没有准备好的情况,也无法判断该数据多久会准备好。但是在并发的情况下相比阻塞 I/O 来说它的性能会好很多

异步 I/O

其实通过阻塞或者非阻塞 I/O,你能发现一个问题,其实拷贝数据都是由内核完成的,那又何必让应用进程去触发拷贝这个操作呢,由内核直接完成不就好了?

所以就出现了异步 I/O 模型

image.png

比如有一个读取数据的请求,应用只需要向内核发送一个 read,告诉内核它要读取数据后即刻返回。

之后内核收到请求并且建立一个信号连接,当数据准备就绪,内核会主动把数据从内核复制到用户空间,等所有操作都完成之后,内核再发起一个通知告诉应用,完成了所有操作,应用程序可以读取数据了,这就是异步 I/O 模型。

异步 IO 的好处是将发送询问请求、发送接收数据请求两个请求合并为一次请求就可以完成状态询问和数拷贝的所有操作,并且无阻塞,内核准备好数据后直接通知。

信号驱动模型

image.png

信号驱动就是进程发起一个 IO 操作,会向内核注册一个信号处理程序,然后立即返回

内核将数据报准备好后会发送一个信号给进程,这时候进程便可以在信号处理程序中调用 IO 处理数据报。

I/O 多路复用

image.png

I/O 多路复用解决的问题就是单线程怎么管理多个 socket 连接,内核负责轮询所有 socket,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。

其主要有 select、poll、epoll 三种多路复用的网络I/O模型

select

select 的设计思路是唤醒模式,通过一个 socket 列表维护所有的 socket,socket 对应文件列表中的 fd,select 会默认限制最大文件句柄数为 1024,间接控制 fd[] 最大为 1024。

  • 如果列表中的 Socket 都没有数据,就挂起进程。
  • 如果有一个 Socket 收到数据,就唤醒进程,将该线程从等待队列中移除,加入到工作队列,然后准备执行 socket 任务。
image.png

那么有个问题来了,如果有多个 socket 任务同时唤醒怎么办,也就是说说有多个 socket 任务同时进来,那到底执行哪个 socket 任务?

所以,当进程被唤醒后,至少有一个 socket 是有数据的,这时候只需要遍历一遍 socket 列表就知道了此次需要执行哪些 socket 了。

缺点:

  • 每次 select 都需要将进程加入到监视 socket 的等待队列,每次唤醒都要将进程从 socket 待队列移除。这里涉及两次遍历操作,而且每次都要将 FDS 列表传递给内核,有一定的开销。

  • 进程被唤醒后,只能知道有 socket 接收到了数据,无法知道具体是哪一个 socket 接收到了数据,所以需要用户进程进行遍历,才能知道具体是哪个 socket 接收到了数据。

poll

poll 其实内部实现基本跟 select 一样,区别在于它们底层组织 fd[] 的数据结构不太一样,从而实现了 poll 的最大文件句柄数量限制去除了

epoll

我们前面说到 select 是需要遍历来解决查询就绪 socket 的,效率很低,epoll 就对此做了改进

image.png
  • 1.拆分:epoll 将添加等待队列和阻塞进程拆分成两个独立的操作,不用每次都去重新维护等待队列
    • 先用 epoll_ctl 维护等待队列 eventpoll,它通过红黑树存储 socket 对象,实现高效的查找,删除和添加。
    • 再调用 epoll_wait 阻塞进程,底层是一个双向链表。显而易见地,效率就能得到提升。

select 的添加等待队列和阻塞进程是合并在一起的,每次调用select()操作时都得执行一遍这两个操作,从而导致每次都要将fd[]传递到内核空间,并且遍历fd[]的每个fd的等待队列,将进程放入各个fd的等待队列中。

  • 2.直接返回有数据的 fd[]:select 进程被唤醒后,是需要遍历一遍 socket 列表,手动获取有数据的 socket,而 epoll 是在唤醒时直接把有数据的 socket 返回给进程,不需要自己去进行遍历查询。

直接返回有数据的 socket 是怎么实现的?

其实就是 epoll 会先注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似 callback 的回调机制,迅速激活这个文件描述符,当进程调用 epoll_wait() 时便得到通知。

epoll对文件描述符的操作有两种模式:LT(level trigger)和 ET(edge trigger)默认为 LT :

  • LT模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件。下次调用epoll_wait时,会再次响应应用程序并通知此事件。
  • ET模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件。

结语

I/O 模型这块儿可是重中之重,作为网络通信的核心,只要你想去大厂一定会被问到,今天这篇文章应该帮你梳理清楚了各个网络 I/O 模型之间的关系以及优缺点,让你对网络 I/O 模型有了更进一步的了解,下次我们准备开始突击 netty ~

在这里,送大家一份自己整理的面试资料,绝不是在网上那种打包下载的,而是自己需要学到某个方向知识的时候,需要看了,去网上挨个找的,最后汇总而成。这部分我是会不断把它完善的,当成自己的小电子书库,不多,但贵在精。

image.png

关注企鹅公号: moon聊技术 ,回复 面试资料 立刻白嫖!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容