七、网络编程之同步非阻塞式网络 IO 模型详解

2023-11-03

上文中探讨了同步阻塞式网络 IO 模型,本文将讨论另一种模型:同步非阻塞 IO 模型。

同步非阻塞式网络 IO 模型详解

同步非阻塞 IO

原理

同步非阻塞 IO(non-blocking IO):应用进程发起 IO 系统调用后,内核立即返回给用户一个状态值,不需要等到 IO 操作彻底完成。比如发生 IO 操作 read 时,它会经历两个阶段:

  1. 第一个阶段,等待数据准备就绪:

    当用户进程发出 read 操作时,如果 kernel 中的数据还没有准备好,那么它并不会 block 用户进程,而是立刻返回一个 error。从用户进程角度讲 ,它发起一个 read 操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个 error 时,它就知道数据还没有准备好,于是它可以再次发送 read 操作。

  2. 第二个阶段,将数据从内核拷贝到用户进程中:

    一旦 kernel 中的数据准备好了,并且又再次收到了用户进程的 system call,那么它马上就将数据拷贝到了用户内存,然后返回正确的返回值。

在这里插入图片描述

所以,在非阻塞式 IO 中,用户进程其实是需要不断的主动询问 kernel 数据准备好了没有。非阻塞的接口相比于阻塞型接口的显著差异在于被调用之后立即返回

产生的问题:不断轮询 kernel 数据准备是否准备就绪将大幅度推高 CPU 占用率;此外,在这个方案中 read() 更多的是起到检测“操作是否完成”的作用,实际操作系统提供了更为高效的检测“操作是否完成“作用的接口,例如 select()多路复用模式,可以一次检测多个连接是否活跃,详细可以参考本系列的后续文章。

代码实现

Linux 下,可以通过文件描述符设置使的 Socket API 变为 non-blocking。具体可以使用如下的函数将某句柄(套接字文件描述符) fd 设为非阻塞状态:

#include <unistd.h>
#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */);
功能:改变已打开的文件性质,fcntl针对描述符提供控制。
参数:
    fd:操作的文件描述符
    cmd:操作方式
    arg:针对cmd的值,fcntl能够接受第三个参数int arg。
返回值:
    成功:返回某个其他值
    失败:-1
    
其中 fcntl 函数有5种功能:
1) 复制一个现有的描述符(cmd=F_DUPFD)
2) 获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD)
3) 获得/设置文件状态标记(cmd=F_GETFL或F_SETFL)
4) 获得/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN)
5) 获得/设置记录锁(cmd=F_GETLK, F_SETLK或F_SETLKW)
    
// 获取原来的flags
int flags = fcntl(fd, F_GETFL);
// 获取新的特性
flag |= O_NONBLOCK;   // 位或:表示追加的方式,等价于 flags = flags | O_NONBLOCK;
// 设置新的flags
fcntl(fd, F_SETFL, flags);

//等价于
fcntl( fd, F_SETFL, O_NONBLOCK );

在非阻塞状态下,read() 接口在被调用后立即返回,返回值代表了不同的含义。如在本例中

  • read() 返回值大于 0,表示接受数据完毕,返回值即是接受到的字节数;
  • read() 返回 0,表示连接已经正常断开;
  • read() 返回 -1,且 errno 等于 EAGAIN,表示 read 操作还没执行完成;
  • read() 返回 -1,且 errno 不等于 EAGAIN,表示 read 操作遇到系统错误 errno。

详细代码示例参考 GitHub 开源代码 “NIO"部分,下载链接

NIO 总结

  • NIO 网络模型在等待数据阶段是非阻塞状态,所以相对于上一篇文章中的 BIO,其在一定程度上提高服务端的并发量,但是这是在消耗 CPU 资源不断轮询的基础上获得的;
  • 实际场景中并不会单独使用 NIO 网络模型,但是设置通讯网络为非阻塞的思路将与其他网络模型(比如之后的文章会详细介绍的 epoll)搭配使用以提高模型的并发处理能力。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

七、网络编程之同步非阻塞式网络 IO 模型详解 的相关文章

  • 在 C# 中实例化 python 类

    我已经用 python 编写了一个类 我想通过 IronPython 将其包装到 net 程序集中 并在 C 应用程序中实例化 我已将该类迁移到 IronPython 创建了一个库程序集并引用了它 现在 我如何真正获得该类的实例 该类看起来
  • Rx Framework:在超时时执行操作,而不中断原始可观察序列

    给定一个可观察的源 通过轮询低级设备的 变化 状态生成 observable source metacode IObservable
  • 使用inotify监控文件

    我正在使用 inotify 来监视本地文件 例如使用 root temp inotify add watch fd root temp mask 删除该文件后 程序将被阻止read fd buf bufSize 功能 即使我创建一个新的 r
  • ASP .NET MVC 5 - 客户地址一对一关系

    我在这里查看了论坛 实际上发现了一些类似的问题 但不是相同的问题 类似的解决方案没有给我正确的答案 我正在使用实体框架和代码优先方法来处理 ASP NET MVC 5 我想建立客户 gt 地址一对一关系的模型 我建模的是 客户等级 publ
  • C# 列表框 ObservableCollection

    我正在尝试使用 ListBox DataSource ObservableCollection 但是我不知道如何在 OC 更新时让列表框自动更新 我可以在 OC 上挂接 CollectionChanged 事件 但是我需要对列表框执行什么操
  • 如何解决素数函数的大O表示法?

    我正在尝试理解 Big O 表示法 很抱歉 如果我问的问题太明显了 但我似乎无法理解这一点 我有以下 C 代码函数 我正在尝试为其计算 Big O 表示法 for i 2 i lt 100 i for j 2 j lt i j j if i
  • 如何从c++调用python

    我是Python新手 我尝试像这样从 C 调用 python 脚本 在 Raspberry Pi 中 std string pythonCommand python Callee py a b int res system pythonCo
  • 接口中的私有成员

    是否可以在 NET 接口中创建私有成员 我听说现在可以了 但我的 IDE 拒绝了 public interface IAnimal void SetDefaultName string name ChangeName name privat
  • 当应用程序未聚焦时监听按键

    我有一个应用程序 C 4 0 WPF 它是隐藏的 可以通过单击系统托盘图标或我创建的其他框架 停靠在左侧和最上面的小框架 来显示 My customer wants to add a new way to display the appli
  • 如何告诉 CMake 将构建文件放在哪里?

    我想告诉 CMake 将文件和文件夹输出到不同的文件夹而不是当前文件夹 我在下面讨论的是 CMake 生成的文件 文件 CMakeCache txt 目录 CMakeFiles 文件 生成文件 目录 bin 文件 cmake install
  • 那里有更好的 DateTime.Parse 吗? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道有一个库 付费或免费 能够处理比 DateTime Parse 使用的更常见的日期时间格式 能够
  • 在 C# 4.0 中,是否可以从泛型类型参数派生类?

    我一直在尝试这个 但我似乎无法弄清楚 我想做这个 public abstract class SingletonType
  • CS0246 找不到类型或命名空间名称“ErrorViewModel”(您是否缺少 using 指令或程序集引用?)

    我收到 CS0246 错误代码 我正在做一个 MVC net core 项目 我正在将 Razor 合并到我的 C 代码中 我在进行构建时收到此错误 我在最后一行收到错误 有人能帮我解决这个问题吗 global Microsoft AspN
  • 是否可以从.NET Core中间件检索控制器的操作结果?

    public class UsersController APIControllerBase public UsersController public Client Get return new Client ClientID 1 Las
  • C中的pipe()和fork()

    我需要创建两个子进程 一个子进程需要运行命令 ls al 并将其输出重定向到下一个子进程的输入 而下一个子进程又将对其输入数据运行命令 sort r n k 5 最后 父进程需要读取该数据 已排序的数据 并将其显示在终端中 终端中的最终结果
  • Android NDK - 仅用 C/C++ 编写

    有没有一种可能的方法可以使用 C C 编写整个 NDK 应用程序 而无需像 hello jni 示例项目 HelloJni java 中那样的 Java 入门 类 以某种方式创建一个 HelloJni c 来执行相同的操作 从 Androi
  • 任何浮点密集型代码是否会在任何基于 x86 的架构中产生位精确的结果?

    我想知道使用浮点运算的 C 或 C 代码是否会在任何基于 x86 的体系结构中产生位精确的结果 无论代码的复杂性如何 据我所知 自 Intel 8087 以来的任何 x86 架构都使用准备处理 IEEE 754 浮点数的 FPU 单元 并且
  • 为什么没有参数的函数(与实际函数定义相比)可以编译?

    我刚刚看到某人的 C 代码 我很困惑为什么要编译它 有两点我不明白 The 函数原型与实际函数定义相比没有参数 中的参数函数定义没有类型 include
  • MsBuild 在 Visual Studio Online 上找不到恢复的 NuGet 包

    我尝试构建一个存储在 Visual Studio Online 上的外部 GIT 存储库中的解决方案 它有以下步骤 1 Git 恢复 有效 2 NuGet 恢复 有效 3 构建 不起作用 查看日志时我的第一个猜测是 MsBuild 没有查找
  • 从哪里开始阅读 SQLite 源代码? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想了解sqlite是如何实现的 并且 想阅读源代码 我已经下载了源代码 我应该开始查看代码的哪一部分 SQLite文档页 http

随机推荐

  • 线程的生命周期及五种基本状态

    一 线程的生命周期及五种基本状态 关于Java中线程的生命周期 首先看一下下面这张较为经典的图 上图中基本上囊括了Java中多线程各重要知识点 掌握了上图中的各知识点 Java中的多线程也就基本上掌握了 主要包括 Java线程具有五中基本状
  • 怎么用css设置字体小于12px

    因为浏览器的限制 网页上的字体最小只能设置12px 因为小于12px就会影响浏览效果 但是有时候我们需要将字体设置的很小这就需要用到特殊的手段 用 transform属性设置 用 transform的scale缩放属性将字体缩放 实际上并没
  • 百度编辑器取消高度自动拉长

    首先去下载百度编辑器 引入百度编辑器
  • 在GIT中创建一个空分支

    问题描述 有时候我们需要在GIT里面创建一个空分支 该分支不继承任何提交 没有父节点 完全是一个干净的分支 例如我们需要在某个分支里存放项目文档 使用传统的git checkout命令创建的分支是有父节点的 意味着新branch包含了历史提
  • 二叉树之遍历

    文章目录 一 二叉树的基本概念及实现 1 根结点 2 父结点 3 子结点 4 二叉树数据结构的实现 二 二叉树的遍历方法 1 前序遍历 2 中序遍历 3 后序遍历 4 层序遍历 三 几种遍历的实现 1 递归方法实现 2 迭代方法实现 3 M
  • 浏览器获取当前位置

    p window navigator geolocation对象存在3个方法 p p 1 getCurrentPosition 获取当前地理位置 p p 2 watchPosition 监视位置信息 p p 3 clearWatch 停止获
  • shell脚本监控Tomcat并重启发送短信

    bin sh TomcatID ps ef grep tomcat grep w tomcat grep v grep awk print 2 StartTomcat tomcat startup path WebUrl www xxx c
  • 固高运动控制卡跟随运动(Follow 运动模式)

    固高运动控制卡跟随运动 Follow 运动模式 一 Follow 运动模式指令列表 固高运动控制卡开发资料 关注我免费下载 GT PrfFollow 设置指定轴为 Follow 运动模式 GT SetFollowMaster 设置 Foll
  • 基于Vshare插件实现vue分享功能

    Vue中引入分享功能插件 一度为快 实现 引入插件 npm config set strict ssl false npm install vshare S 页面实现
  • go语言有哪些web框架

    前言 由于工作需要 这些年来也接触了不少的开发框架 Golang的开发框架比较多 不过基本都是Web 框架 为主 这里稍微打了个引号 因为大部分 框架 从设计和功能定位上来讲 充其量都只能算是一个组件 需要项目使用的话得自己四处再去找找其他
  • python基础练习题(二) --分支结构练习题

    一 单选题 1 哪个选项是实现多路分支的最佳控制结构 5 0分 A if B if elif else C try D if else 2 关于程序的控制结构 哪个选项的描述是错误的 5 0分 A 流程图可以用来展示程序结构 B 顺序结构有
  • Echarts散点图筛选新玩法dataZoom

    目录 前言 一 引入Echarts5 4 3 二 新建index html 三 绑定Echarts展示元素 四 初始数据绑定 五 option设置 六 效果展示 七 参数说明 总结 前言 如果您在日常的工作当中也会遇到如下场景 需要在线对已
  • 也谈系统设计的一些原则

    在进行系统设计时 不仅要考虑软件的功能性需求 还要考虑非功能性需求 比如软件的性能 Performance 可扩展性 Scalability 系统的稳定性 Reliability 部署 Deployment 和更新 Upgrade 可维护性
  • OpenCV —— 边缘检测(Roberts、Prewitt、Sobel、Scharr、Kirsch、Robinson、Canny边缘检测)

    边缘检测 Roberts 算子 Prewitt 边缘检测 Sobel 边缘检测 Scharr算子 Krisch 算子和Robinson 算子 Canny 边缘检测 图像的边缘指的是灰度值发生急剧变化的位置 在图像形成过程中 由于亮度 纹理
  • mysql 中 if 、left、mod语句的使用(计算特殊奖金Mysql)

    Mysql三种简单语句 语法结构 IF 条件 T1 F2 用法 条件表达式得到不同的结果 当 条件为真时返回 T1 的值 否则返回 F2 语法结构 Left 字符串 位序 用法 当位序位N时 输出字符串第N个字符 语法结构 Mod 被求余数
  • Python实践TensorFlow和Kivy卷积神经网络计算机视觉应用

    特点 使用卷积神经网络 CNN 深度学习模型和 Python 的计算机视觉应用程序 解释了传统的机器学习管道 并将在其中分析图像数据集 学习人工神经网络 ANN 在使用遗传算法对其进行优化之前 用 Python 从头开始构建一个 对比传统手
  • T1292:宠物小精灵之收服

    宠物小精灵之收服 宠物小精灵是一部讲述小智和他的搭档皮卡丘一起冒险的故事 一天 小智和皮卡丘来到了小精灵狩猎场 里面有很多珍贵的野生宠物小精灵 小智也想收服其中的一些小精灵 然而 野生的小精灵并不那么容易被收服 对于每一个野生小精灵而言 小
  • 近期大型攻防演练观感及未来攻防趋势判断

    先说结论 今年大型攻防演练的观感 大量的国产商业软件供应链厂商的大量商业软件0day被用来攻击 以安全产品 OA cms 办公软件为主 社工 钓鱼又玩出了新花样 红队这帮人估计去电诈团队培训回来的 开源软件的Nday 0day漏洞及投毒仍然
  • VB 中的基本数据类型

    VB基本数据类型 VB 6 O提供的基本数据类型主要有 字符型数据 数值型数据 货币类型 字节类型 布尔类型 日期类型 通用类型 无符号类型 对象类型等9种数据类型 1 字符型数据 字符型数据 String 用以定义一个字符序列 在内存中一
  • 七、网络编程之同步非阻塞式网络 IO 模型详解

    上文中探讨了同步阻塞式网络 IO 模型 本文将讨论另一种模型 同步非阻塞 IO 模型 同步非阻塞式网络 IO 模型详解 同步非阻塞 IO 原理 同步非阻塞 IO non blocking IO 应用进程发起 IO 系统调用后 内核立即返回给