高性能网络编程 - 解读5种I/O模型

news2024/11/25 12:51:39

文章目录

  • 服务端处理网络请求流程图
  • 基础概念
    • 阻塞调用 vs 非阻塞调用
    • 同步处理 vs 异步处理
    • 阻塞、非阻塞 和 同步、异步的区别
    • recvfrom 函数
  • 五种I/O模型
    • I/O模型1:阻塞式 I/O 模型(blocking I/O)
    • I/O模型2:非阻塞式 I/O 模型(non-blocking I/O)
    • I/O模型3:I/O 复用模型(I/O multiplexing)
    • I/O模型4:信号驱动式 I/O 模型(signal-driven I/O)
    • I/O模型5:异步 I/O 模型(即AIO,全称asynchronous I/O)
  • 5 种 I/O 模型总结

在这里插入图片描述


服务端处理网络请求流程图

在这里插入图片描述

大致流程如下:

  • 1)获取请求数据,客户端与服务器建立连接发出请求,服务器接受请求(1-3);
  • 2)构建响应,当服务器接收完请求,并在用户空间处理客户端的请求,直到构建响应完成(4);
  • 3)返回数据,服务器将已构建好的响应再通过内核空间的网络 I/O 发还给客户端(5-7)。

设计服务端并发模型时,主要有如下两个关键点:

  • 1)服务器如何管理连接,获取输入数据;
  • 2)服务器如何处理请求。

以上两个关键点最终都与操作系统的 I/O 模型以及线程(进程)模型相关,我们先详细看一下I/O模型 。


基础概念

阻塞调用 vs 非阻塞调用

  • 阻塞调用是指调用结果返回之前,当前线程会被挂起,调用线程只有在得到结果之后才会返回;
  • 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

两者的最大区别在于被调用方在收到请求到返回结果之前的这段时间内,调用方是否一直在等待。

阻塞是指调用方一直在等待而且别的事情什么都不做;非阻塞是指调用方先去忙别的事情。


同步处理 vs 异步处理

  • 同步处理是指被调用方得到最终结果之后才返回给调用方;
  • 异步处理是指被调用方先返回应答,然后再计算调用结果,计算完最终结果后再通知并返回给调用方

阻塞、非阻塞 和 同步、异步的区别

阻塞、非阻塞和同步、异步其实针对的对象是不一样的

  • 1)阻塞、非阻塞的讨论对象是调用者
  • 2)同步、异步的讨论对象是被调用者

recvfrom 函数

recvfrom 函数(经 Socket 接收数据),这里把它视为系统调用

阻塞式 I/O 模型中的 recvfrom 是一个用于接收数据报的系统调用或函数。它通常用于网络编程中,特别是在UDP协议中。这个函数会阻塞应用程序的进程,直到有数据报准备好可以被接收。

具体来说,recvfrom 通常用于接收来自网络的数据报,例如从套接字(socket)中接收数据。当应用程序调用 recvfrom 时,如果没有数据报可用,它会等待直到有数据报到达,然后将数据报的内容复制到应用程序指定的缓冲区中,并返回成功。

在阻塞式 I/O 模型中,这个调用会导致应用程序阻塞,即应用程序的执行被暂停,直到数据可用为止。这通常意味着应用程序无法执行其他操作,直到 recvfrom 返回并提供接收的数据。这种模型在某些情况下非常简单,但也可能导致应用程序出现延迟,因为它必须等待数据的到达。


一个输入操作通常包括两个不同的阶段:

1)等待数据准备好;
2)从内核向进程复制数据。

对于一个套接字上的输入操作,

  • 第一步通常涉及等待数据从网络中到达。当所等待分组到达时,它被复制到内核中的某个缓冲区。
  • 第二步就是把数据从内核缓冲区复制到应用进程缓冲区。

实际应用程序在系统调用完成上面的 2 步操作时,

  • 调用方式的阻塞、非阻塞,
  • 操作系统在处理应用程序请求时,处理方式的同步、异步处理的不同,可以分为 5 种 I/O 模型

五种I/O模型

I/O模型1:阻塞式 I/O 模型(blocking I/O)

在这里插入图片描述
在阻塞式 I/O 模型中,应用程序在从调用 recvfrom 开始到它返回有数据报准备好这段时间是阻塞的,recvfrom 返回成功后,应用进程开始处理数据报。

  • 比喻:一个人在钓鱼,当没鱼上钩时,就坐在岸边一直等。
  • 优点:程序简单,在阻塞等待数据期间进程/线程挂起,基本不会占用 CPU 资源。
  • 缺点:每个连接需要独立的进程/线程单独处理,当并发请求量大时为了维护程序,内存、线程切换开销较大,这种模型在实际生产中很少使用。

I/O模型2:非阻塞式 I/O 模型(non-blocking I/O)

在这里插入图片描述

在非阻塞式 I/O 模型中,应用程序把一个套接口设置为非阻塞,就是告诉内核,当所请求的 I/O 操作无法完成时,不要将进程睡眠。

而是返回一个错误,应用程序基于 I/O 操作函数将不断的轮询数据是否已经准备好,如果没有准备好,继续轮询,直到数据准备好为止

  • 比喻:边钓鱼边玩手机,隔会再看看有没有鱼上钩,有的话就迅速拉杆。
  • 优点:不会阻塞在内核的等待数据过程,每次发起的 I/O 请求可以立即返回,不用阻塞等待,实时性较好。
  • 缺点:轮询将会不断地询问内核,这将占用大量的 CPU 时间,系统资源利用率较低,所以一般 Web 服务器不使用这种 I/O 模型。

EWOULDBLOCK 是一个错误码(或错误常量),通常在网络编程和非阻塞 I/O 中使用。它表示某个操作(通常是非阻塞的)因为当前状态而无法立即执行,但并不算是一种错误。在不同的操作系统和编程语言中,它有时也被称为 EAGAIN,表示 “操作再次尝试”。

当你在非阻塞模式下进行 I/O 操作(如读取或写入数据),有时可能会遇到 EWOULDBLOCK 错误。这通常发生在以下情况下:

  1. 针对非阻塞套接字的读取操作,但没有数据可供读取,因此需要稍后再次尝试。
  2. 针对非阻塞套接字的写入操作,但发送缓冲区已满,因此需要稍后再次尝试。

这并不是一种严重的错误,而是提示应用程序需要稍后再次尝试相同的操作,因为当前条件不允许立即执行。应用程序可以通过重新调用相同的操作来处理 EWOULDBLOCK 错误,直到操作成功完成。

在C语言中,通常使用 errno 变量来获取最后一次发生的错误码,而 EWOULDBLOCK 可以表示为 EAGAIN。例如:

if (recvfrom(socket_fd, buffer, buffer_size, 0) == -1) {
    if (errno == EWOULDBLOCK || errno == EAGAIN) {
        // 需要稍后再次尝试
    } else {
        // 处理其他错误
    }
}

这样,你可以在适当的情况下处理 EWOULDBLOCK 错误,以实现非阻塞的I/O操作。


I/O模型3:I/O 复用模型(I/O multiplexing)

在这里插入图片描述

在 I/O 复用模型中,会用到 Select 或 Poll 函数或 Epoll 函数(Linux 2.6 以后的内核开始支持),这两个函数也会使进程阻塞,但是和阻塞 I/O 有所不同。

这两个函数可以同时阻塞多个 I/O 操作,而且可以同时对多个读操作,多个写操作的 I/O 函数进行检测,直到有数据可读或可写时,才真正调用 I/O 操作函数。

  • 比喻:放了一堆鱼竿,在岸边一直守着这堆鱼竿,没鱼上钩就玩手机。
  • 优点:可以基于一个阻塞对象,同时在多个描述符上等待就绪,而不是使用多个线程(每个文件描述符一个线程),这样可以大大节省系统资源。
  • 缺点:当连接数较少时效率相比多线程+阻塞 I/O 模型效率较低,可能延迟更大,因为单个连接处理需要 2 次系统调用,占用时间会有增加。

众所周之,Nginx这样的高性能互联网反向代理服务器大获成功的关键就是得益于Epoll


I/O模型4:信号驱动式 I/O 模型(signal-driven I/O)

在这里插入图片描述

在信号驱动式 I/O 模型中,应用程序使用套接口进行信号驱动 I/O,并安装一个信号处理函数,进程继续运行并不阻塞。

当数据准备好时,进程会收到一个 SIGIO 信号,可以在信号处理函数中调用 I/O 操作函数处理数据。

  • 比喻:鱼竿上系了个铃铛,当铃铛响,就知道鱼上钩,然后可以专心玩手机。
  • 优点:线程并没有在等待数据时被阻塞,可以提高资源的利用率。
  • 缺点:信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知。

信号驱动 I/O 尽管对于处理 UDP 套接字来说有用,即这种信号通知意味着到达一个数据报,或者返回一个异步错误。

但是,对于 TCP 而言,信号驱动的 I/O 方式近乎无用,因为导致这种通知的条件为数众多,每一个来进行判别会消耗很大资源,与前几种方式相比优势尽失


I/O模型5:异步 I/O 模型(即AIO,全称asynchronous I/O)

在这里插入图片描述

由 POSIX 规范定义,应用程序告知内核启动某个操作,并让内核在整个操作(包括将数据从内核拷贝到应用程序的缓冲区)完成后通知应用程序。

这种模型与信号驱动模型的主要区别在于:信号驱动 I/O 是由内核通知应用程序何时启动一个 I/O 操作,而异步 I/O 模型是由内核通知应用程序 I/O 操作何时完成。

  • 优点:异步 I/O 能够充分利用 DMA 特性,让 I/O 操作与计算重叠。
  • 缺点:要实现真正的异步 I/O,操作系统需要做大量的工作。目前 Windows 下通过 IOCP 实现了真正的异步 I/O

而在 Linux 系统下,Linux 2.6才引入,目前 AIO 并不完善,因此在 Linux 下实现高并发网络编程时都是以 IO 复用模型模式为主。


5 种 I/O 模型总结

在这里插入图片描述

从上图中我们可以看出,越往后,阻塞越少,理论上效率也是最优。

这五种 I/O 模型中,前四种属于同步 I/O,因为其中真正的 I/O 操作(recvfrom)将阻塞进程/线程,只有异步 I/O 模型才与 POSIX 定义的异步 I/O 相匹配。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1191157.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实用技巧:嵌入式人员使用http服务模拟工具模拟http服务器测试客户端get和post请求

文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/134305752 红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结…

卡尔曼滤波EKF

目录 一、概述 二、卡尔曼滤波的5个公式 三、应用案例:汽车运动 四、应用案例:温度估计 五、总结 一、概述 初学者对于卡尔曼滤波5个公式有点懵,本文先接地气地介绍5个公式,然后举两个常用例子加强理解,同时附有M…

杰里6969系列控制RGB彩灯模式

1、任务目标 实现可以接收到APP传输过来的数据,可以通过传输的数据前几个字节识别到所需要控制的模式,然后提取数据的后几个字节来分别对RGB灯进行不同的的PWM波控制,从而实现跳变和渐变的效果。 2.跳变(分布调试记录&#xff09…

创建多层级行索引,创建多层级行索引的DataFrameMultiIndex.from_product()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 创建多层级行索引, 创建多层级行索引的DataFrame MultiIndex.from_product() [太阳]选择题 使用pd.MultiIndex.from_product(),下列输出正确的是: import pandas as pd…

一键批量删除文件名中的空格,高效整理您的文件

你是否曾经因为文件名中多余的空格而烦恼?这些空格不仅影响了文件的美观,还可能导致一些不必要的错误。现在,我们向您介绍一款全新的工具,它可以帮助您一键批量删除文件名中的空格,让您的文件整理更加轻松、高效&#…

一款功能强大的web目录扫描器专业版

dirpro 简介 dirpro 是一款由 python 编写的目录扫描器,操作简单,功能强大,高度自动化。 自动根据返回状态码和返回长度,对扫描结果进行二次整理和判断,准确性非常高。 已实现功能 可自定义扫描线程 导入url文件进…

劲松中西医医院专家谭巍医生解读:生殖衣原体阳性是什么意思

生殖衣原体阳性是指生殖系统出现了衣原体感染。衣原体是我们身体中常见的菌群,生殖系统常见的衣原体有:沙眼衣原体,当然还包括一些支原体,如:人型支原体、解脲支原体等,都可引起生殖系统出现一系列的感染症…

华为L410上制作内网镜像模板02

原文链接:华为L410上制作离线安装软件模板02 hello,大家好啊,今天给大家带来第二篇在内网搭建Apache服务器,用于安装完内网操作系统后,在第一次开机时候,为系统安装软件的文章,今天给大家介绍在…

Linux常见指令:从基础到理论

前言 目录 前言 1. find指令 拓展 2. grep指令 拓展 sort指令 uniq指令 wc指令 3. zip/unzip指令 4. tar指令 5. uname指令 拓展 6. Linux常用热键 7. 关机 8. rz指令 拓展 scp指令 9. shell命令以及运行原理 Linux常见指令是使用Linux系统时必不可少的一部分。通过掌握…

【QML】Qt和QML获取操作系统类型

1. Qt获取系统类型 //方法 QSysInfo::productType()//举例&#xff1a; if(QSysInfo::productType() "windows") {qDebug() << "windows system"; }官方说明&#xff1a; [static] QString QSysInfo::productType() Returns the product name of …

【数据结构】树与二叉树(七):二叉树的遍历

文章目录 5.1 树的基本概念5.1.1 树的定义5.1.2 森林的定义5.1.3 树的术语5.1.4 树的表示 5.2 二叉树5.2.1 二叉树1. 定义2. 特点3. 性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉…

MySQL -- 事务管理

MySQL – 事务管理 文章目录 MySQL -- 事务管理一、理解事务1.如果CURD不加控制&#xff0c;会有什么问题2.事务的概念 二、MySQL中的事务1.事务的版本支持2.事务提交方式3.事务常见操作方式3.1.事务的开始与回滚3.2.证明未commit&#xff0c;客户端崩溃&#xff0c;MySQL自动会…

Vue脚手架学习笔记

视频 Vue脚手架学习笔记 1. 脚手架设置相关内容1.1 各文件的作用1.2 关闭语法检查 2. 组件的使用2.1 单文件组件的使用&#xff08;组件使用的三个步骤&#xff09;2.2 prop配置项&#xff1a;父向子传数据2.2.1 数组方式2.2.2 类型限制2.2.3 默认值、必要性 2.3 ref &#xf…

C# OpenCvSharp 玉米粒计数

效果 项目 代码 using OpenCvSharp; using System; using System.Drawing; using System.Text; using System.Windows.Forms;namespace OpenCvSharp_Demo {public partial class frmMain : Form{public frmMain(){InitializeComponent();}string fileFilter "*.*|*.bmp;…

2023年CCF非专业级别软件能力认证第二轮 (CSP-S)提高级C++语言试题

2023年CCF非专业级别软件能力认证第二轮 &#xff08;CSP-S&#xff09;提高级C语言试题 编程题第 1 题 问答题 密码锁&#xff08;lock&#xff09; 题目描述 小Y有一把五个拨圈的密码锁。如图所示&#xff0c;每个拨圈上是从0到9的数字。每个拨圈都是从0到9的循环&#xf…

【算法 | 模拟No.4】AcWing 756. 蛇形矩阵 AcWing 40. 顺时针打印矩阵

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【AcWing算法提高学习专栏】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&a…

汉诺塔 --- 递归回溯算法练习一

目录 1. 什么叫汉诺塔 2. 分析算法原理 2.1. 当盘子的数量为1 2.2. 当盘子的数量为2 2.3. 当盘子的数量为3时 3. 编写代码 3.1. 挖掘重复子问题 3.2. 只关心某一个子问题如何处理 3.3. 递归的结束条件 3.4. 代码的编写 4. 递归展开图分析 1. 什么叫汉诺塔 力扣上的原…

Go并发编程(上)

目录 一、go语言当中的协程 二、MPG模型介绍 三、Goroutine 的使用 3.1 协程的开启 3.2 优雅地等待子协程结束 四、捕获子协程的panic 五、管道Channel 5.1、认识管道 5.2、Channel的遍历和关闭 5.3 、用管道实现生产者消费者模型 5.4、Channel一些使用细节和注意事…

揭秘!2024年热门的图标设计工具

在这个瞬息万变的世界里&#xff0c;设计师们对创新和实用的工具的渴望日益热切。我们需要时刻紧跟潮流&#xff0c;发掘和尝试最新&#xff0c;最有价值的图标设计工具&#xff0c;才能在剧烈的市场竞争中引人注目。以下是我们细心挑选的2024年图标设计工具的热门推荐&#xf…

CentOS 7 双网卡绑定热备 —— 筑梦之路

为什么需要&#xff1f; 1. 增强网络的可靠性 2. 保障服务的可持续性 3. 降低网卡故障带来的不良影响 有哪些模式&#xff1f; 模式0&#xff1a;轮询策略&#xff08;round robin&#xff09;&#xff0c;mode0&#xff0c;优点&#xff1a;流量提高一倍缺点&#xff1a;需要接…