【计算机网络】高级IO初步理解

文章目录

  • 1. 什么是IO?
    • 什么是高效 IO?
  • 2. IO的五种模型
    • 五种IO模型的概念理解
      • 同步IO与异步IO
      • 整体理解
  • 3. 阻塞IO
  • 4. 非阻塞IO
    • setnonblock函数
    • 为什么非阻塞IO会读取错误?
    • 对错误码的进一步判断
    • 检测数据没有就绪时,返回做一些其他事情
    • 完整代码
      • mytest.cc
      • makefile

1. 什么是IO?

IO:表示 输入 输出


当对方把连接建立好,但是不发数据
而我是一个线程,正在调用 read 来读,就会阻塞,一直等数据发送过来
读取条件不满足的情况下,read或recv 只会等待


无论是有数据时的拷贝 ,还是没有数据时的等待
两者的时间成本,全都算到了用户头上

在用户的角度,IO= 等+数据拷贝

什么是高效 IO?

单位时间内, 等的比重越低, IO效率越高

当IO条件满足时,称为 IO事件就绪

2. IO的五种模型

五种IO模型的概念理解

如:钓鱼假设分为两步 , 钓鱼 = 等 + 钓

在鱼竿的钩子上挂一个鱼漂,浮在水面上,用来恒定鱼竿下水的深度
当鱼漂上下摆动时,就可以知道当前有鱼上钩了


1. 张三一般喜欢专注于一件事, 所以当张三钓鱼等待时,就会一直盯着鱼漂看 是否有鱼上钩
过了一段时间,鱼漂动了,张三拉动鱼竿,将鱼钓上来了,放入桶中
继续刚才钓鱼的动作
张三在钓鱼的过程中,只盯着鱼漂看,不干其他事情


2. 李四天生好动, 所以当李四钓鱼时,就不怎么看鱼漂,会左顾右看的张望
当发现鱼咬钩后,就把鱼钓上来,放入桶中
继续刚才钓鱼的动作
李四在钓鱼的过程中,除了看鱼漂,还做其他事情


3. 王五比较特别, 当王五钓鱼时,在鱼竿的顶部放上一个铃铛,等待鱼上钩
等待过程中,王五做着自己的事情
当王五听到铃铛响了时,就拉动鱼竿,将鱼钓上来了,放入桶中
继续刚才钓鱼的动作
王五在钓鱼的过程中,不看鱼漂,只听铃铛来判断是否有鱼上钩


4. 赵六是周围的首富,开皮卡来钓鱼,皮卡上装了10根鱼竿 (首富是来体验生活的)
使用10根鱼竿一起钓鱼,赵六就从前往后 依次查看 是否有鱼漂在动


5. 田七是方圆500公里的首富 (田七比赵六有钱)
田七很忙,每天都有各种会议要开,而且田七并不是想钓鱼,而是喜欢吃鱼
所以就 让司机小王帮忙去钓鱼
当鱼桶满了后,给田七打电话,就会来人把鱼带走
小王在钓鱼时,田七也正在开会


张三和李四钓是一样的,差别在等待鱼上钩的方式不同
张三为 鱼漂不动,他不动
李四为 鱼漂不动,会立马返回去做其他事情


张三的钓鱼方式 称为 阻塞IO
(数据没有就绪,调用的read接口不会返回)


李四的钓鱼方式 称为 非阻塞IO
(检测一次若没有数据,则会立马返回,过一段时间可以再次检测)


王五在鱼还没有钓上来之前,就知道当铃铛响了,就应该拉动鱼竿
王五的钓鱼方式 称为 信号驱动IO


赵六一次管理多个鱼竿,赵六的钓鱼方式称为 多路复用或多路转接

在这几个人中,赵六的钓鱼效率比较高
因为赵六的鱼竿比较多,所以鱼上钩的概率大 即等待时间比较短
所以赵六的钓鱼效率比较高


同步IO与异步IO

前四个人都要钓鱼的过程,所以都称为 同步IO

田七没有参与钓鱼的过程,没有等 ,也没有钓,只是 发起钓鱼的过程
田七的钓鱼方式 称为 异步IO


整体理解

钓 可以看作 数据拷贝
张三 李四 等人 可以看作 进程
田七可以看作是一个进程,司机小王可以看作是操作系统
鱼竿可以看作 文件描述符
鱼 可以看作是 数据
鱼咬钩 或 鱼漂动 、铃铛响 可以看作 IO事件就绪


一个进程 在文件描述符上读取数据时,若数据没有就绪,当前进程只能挂起等待
直到有IO时间就绪,数据才可以拷贝到对应的上层

3. 阻塞IO

阻塞IO:数据没有就绪,调用的read接口不会返回


通过使用 read 函数 从键盘中读,当代码写好时,若什么也不输入,则什么也不显示 则为阻塞IO

输入 man 2 read

从一个文件描述符 中 去读count个数据 到 buf缓冲区中
若获取成功,则返回 字节数据
若获取 为0,则表示读到文件结尾
若获取为-1,则表示失败,并设置错误码


0表示标准输入流
从标准输入流中 读buffer数组大小的数据 发送到 buffer中

运行可执行程序后,一直不输入,则导致read在等待,直到有数据输入才进行数据拷贝

4. 非阻塞IO

非阻塞IO:检测一次若没有数据,则会立马返回 做其他事情,过一段时间可以再次检测


通过使用 read 函数 从键盘中读,当代码写好时,就是不输入
通过这样的方式,模拟读取条件不满足的情况下,read只会等待的情况

在上述阻塞IO的代码的基础上 进行修改


setnonblock函数

输入 man fcntl

第一个参数为 文件描述符
第二个参数 表示 你要对文件描述符干什么
获得/设置文件状态标记(cmd=F_GETFLF_SETFL)

通过设置文件状态标记,就可以将一个文件描述符 变为 非阻塞

使用 F_GETFL,将当前文件描述符的属性取出来
使用 F_SETFL,将文件描述符 状态进行设置,并加上一个 O_NONBLOCK (非阻塞) 参数

若函数返回 -1,则表示失败


创建一个函数 setnonblock,将文件描述符设置为非阻塞状态
先使用F_GETFL,获取对应文件描述符的属性
若获取失败,则返回错误原因和错误码
若获取成功,则使用 F_SETFL 将文件描述符状态设为非阻塞状态


为什么非阻塞IO会读取错误?

在主函数main中,将标准输入流改为非阻塞状态
并根据read的三种返回值,分别设置 返回提示 : 读取成功、文件结尾 和 读取错误


当将标准输入流设置为非阻塞状态后
再次运行可执行程序,直接就会读取失败
在调用read时,发现数据没有就绪 (当前读取检测速度太快,还没有输入,就报错了)

所以一旦底层数据没有就绪,就以出错的形式返回,但是不算真正的出错


但这样就没办法区分是真正出错还是 底层没有数据了
所以就通过出错码 进行进一步判断

对错误码的进一步判断

EAGAIN EWOULDBLOCK 都是系统设置的,错误码都是11
用于判断没出错,但是以出错的形式返回 的错误码
若为真,则下次继续检测即可


若IO被信号中断,则重新检测


检测数据没有就绪时,返回做一些其他事情

非阻塞IO,是可以做到 当检测数据没有就绪 时,就返回做一些其他事情


定义一个 包装器 其参数为void 返回值为void ,并将其重命名为 func_t 类型
定义一个vetcor数组 ,其类型为 func_t


设置三个任务,分别为PrintLog OperMysql CheckNet


在创建LoadTask函数,将任务分别插入到funcs数组中


在主函数main中,调用 LoadTask函数 以此加载任务


创建一个 HandlerALLTask函数,用于遍历 vector数组 ,数组元素为任务
当数据没有就绪时,就返回 处理任务


完整代码

mytest.cc

#include<iostream>
#include<unistd.h>
#include<fcntl.h>
#include<cstdio>
#include<cstring>
#include<vector>
#include<functional>
using namespace std;//任务
void PrintLog()//打印日志
{cout<<"这是一个打印日志例程"<<endl;
}void OperMysql()
{cout<<"这是一个操作数据库的例程"<<endl;
}void CheckNet()
{cout<<"这是一个检测网络状态的例程"<<endl;
}using func_t =function<void(void)>;
vector<func_t>  funcs;void LoadTask()
{funcs.push_back(PrintLog);funcs.push_back( OperMysql);funcs.push_back(CheckNet);
}void HandlerALLTask()
{//遍历vector数组for(auto& func:funcs){func();}
}void SetNonBlock(int fd)//将文件描述符设为非阻塞
{int fl=fcntl(fd,F_GETFL);//获取当前文件描述符的指定状态标志位if(fl<0)//获取失败{cerr<<"error string: "<<strerror(errno)<<"error code: "<<errno<<endl;}fcntl(fd,F_SETFL,fl | O_NONBLOCK);//将文件描述符状态设为非阻塞状态
}int main()
{char buffer[64];SetNonBlock(0);//将标准输入流 改为非阻塞状态LoadTask();//加载任务while(true){//0表示标准输入流ssize_t n=read(0,buffer,sizeof(buffer)-1);//检测条件是否就绪if(n>0)//读取成功{buffer[n-1]=0;    cout<<"echo# "<<buffer<<endl; }else if(n==0)//读到文件结尾{cout<<"end file"<<endl;}else//读取失败 {if(errno==EAGAIN || errno ==EWOULDBLOCK){//若为真,说明没出错,只是以出错返回//底层数据没有准备好,下次继续检测HandlerALLTask();//遍历数组 处理任务sleep(1);cout<<"data not  ready"<<endl;continue;}else if(errno == EINTR){//IO被信号中断,需要重新检测continue;}else //真正的错误{cout<<"read error"<<"error string: "<<strerror(errno)<<"error code: "<<errno<<endl;break;}}sleep(1);}return 0;
}

makefile

mytest:mytest.ccg++ -o $@ $^ -std=c++11.PHONY:clean
clean:rm -f mytest

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

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

相关文章

Flutter笔记 - ListTile组件及其应用

Flutter笔记 ListTile组件及其应用 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/133411883 目 录 1. …

计算机毕设 大数据工作岗位数据分析与可视化 - python flask

文章目录 0 前言1 课题背景2 实现效果3 项目实现3.1 概括 3.2 Flask实现3.3 HTML页面交互及Jinja2 4 **完整代码**5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要…

R实现数据分布特征的视觉化——多笔数据之间的比较

大家好&#xff0c;我是带我去滑雪&#xff01; 如果要对两笔数据或者多笔数据的分布情况进行比较&#xff0c;Q-Q图、柱状图、星形图都是非常好的选择&#xff0c;下面开始实战。 &#xff08;1&#xff09;绘制Q-Q图 首先导入数据bankwage.csv文件&#xff0c;该数据集…

VSC-HVDC直流输电matlab仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; VSC-HVDC直流输电仿真&#xff0c;换流站采用两电平结构&#xff0c;全控型器件&#xff08;IGBT&#xff09;&#xff0c;采用双环控制&#xff0c;包括电压外环&#xff0c;电流内环&#xff0c;分为d、q两…

使用关键字abstract 声明抽象类-PHP8知识详解

抽象类只能作为父类使用&#xff0c;因为抽象类不能被实例化。抽象类使用关键字abstract 声明&#xff0c;具体的使用语法格式如下&#xff1a; abstract class 抽象类名称{ //抽象类的成员变量列表 abstract function 成员方法1(参数); //抽象类的成员方法 abstract functi…

网络基础知识面试题1

VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)

GPU(国内外发展,概念参数(CUDA,Tensor Core等),类别,如何选型,NPU,TPU)

目录 前言 1.国内外GPU发展简述 2.GPU概念参数和选择标准 2.1 CUDA 2.2 Tensor Core 2.3 显存容量和显存位宽 2.4 精度 2.5 如何选择GPU 3.常见GPU类别和价格 3.1 GPU类别 3.2 GPU价格&#xff08;部分&#xff09; 3.3 GPU云服务器收费标准&#xff08;以阿里云为例&a…

五.docker+jenkins自动部署项目

一.敏捷开发相关概念 1.微服务的痛点 再来看一下我们的微服务架构 &#xff0c; 每个组件都需要服务器去部署&#xff0c;加起来可能需要几十个甚至上百个服务器。这样的微服务项目在部署上会遇到什么问题&#xff1f; 需要很多很多的服务器&#xff0c;服务器的采购安装&am…

Day-06 基于 Docker 安装 Nginx 镜像

1.去官方公有仓库查询nginx镜像 docker search nginx 2.拉取该镜像 docker pull nginx 3. 启动镜像&#xff0c;使用nginx服务&#xff0c;代理本机8080端口(测试是不是好使) docker run -d -p 8080:80 --name nginx-8080 nginx docker ps curl 127.0.0.1:8080

微服务保护(Sentinel)

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

云安全之等级保护详解

等级保护概念 网络安全等级保护&#xff0c;是对信息系统分等级实行安全保护&#xff0c;对信息系统中使用的安全产品实行按等级管理&#xff0c;对信息系统中发生的信息安全事件分等级进行响应、处置。 网络安全等级保护的核心内容是&#xff1a;国家制定统一的政策、标准&a…

横向AlGaN/GaN基SBD结构及物理模型数据库的开发

GaN基功率器件凭借其临界电场高、电子饱和漂移速度大、热导率高等优良性能在大功率快充、充电桩、新能源汽车等领域具备广泛应用空间。为进一步助推半导体高频、高功率微电子器件的发展进程&#xff0c;天津赛米卡尔科技有限公司技术团队依托先进的半导体TCAD仿真平台成功开发出…

计算机网络八股

1、请你说说TCP和UDP的区别 TCP提供面向连接的可靠传输&#xff0c;UDP提供面向无连接的不可靠传输。UDP在很多实时性要求高的场景有很好的表现&#xff0c;而TCP在要求数据准确、对速度没有硬件要求的场景有很好的表现。TCP和UDP都是传输层协议&#xff0c;都是为应用层程序服…

【Java 进阶篇】深入了解JDBCTemplate:简化Java数据库操作

数据库操作是几乎所有现代应用程序的一部分。从存储和检索数据到管理业务逻辑&#xff0c;数据库操作是不可或缺的。在Java应用程序中&#xff0c;JDBCTemplate是一种强大的工具&#xff0c;可帮助开发人员轻松进行数据库操作。本文将深入探讨JDBCTemplate&#xff0c;了解它的…

最新Uniapp软件社区-全新带勋章源码

测试环境&#xff1a;php7.1。ng1.2&#xff0c;MySQL 5.6 常见问题&#xff1a; 配置好登录后转圈圈&#xff0c;检查环境及伪静态以及后台创建好应用 上传图片不了&#xff0c;检查php拓展fileinfo 以及public文件权限 App个人主页随机背景图&#xff0c;在前端uitl文件夹里面…

string类的使用方式的介绍

目录 前言 1.什么是STL 2. STL的版本 3. STL的六大组件 4.STL的缺陷 5.string 5.1 为什么学习string类&#xff1f; 5.1.1 C语言中的字符串 5.2 标准库中的string类 5.3 string类的常用接口的使用 5.3.1 构造函数 5.3.2 string类对象的容量操作 5.3.3 string类对象…

2023年中国资产数字化监控运维管理系统行业分析:产品应用领域不断拓展[图]

资产监控运维管理是一门紧密结合生产实际的工程科学&#xff0c;是实现资产有效运营维护的重要手段。资产监控运维管理技术起源于美国和欧洲等国家和地区&#xff0c;经过几十年的理论研究和实际应用&#xff0c;资产监控运维管理技术为提高重大设备资产和系统的可靠性和安全性…

java Spring Boot 手动启动热部署

好 接下来 我们讲一个对开发非常重要的东西 热部署 因为 我们在开发过程中总会希望快点看到效果 或者 你的企业项目一般很大很复杂&#xff0c;重启是一件非常麻烦的事 或者你在和前端同事联调&#xff0c;有一点小问题 你改完就要重启 前端还得等你&#xff0c;非常不友好 那…

PbootCMS SQL注入漏洞

漏洞复现 访问漏洞url 数据库是mysql 构造payload&#xff0c;条件为假时&#xff0c;未查到任何数据 http://x.x.x/index.php?search 1select 0页面回显 构造payload&#xff0c;条件为真时&#xff0c;查询到数据 1select1文笔生疏&#xff0c;措辞浅薄&#xff0c;望各…

SpringMVC系列-4 参数解析器

背景&#xff1a; 本文作为SpringMVC系列的第四篇&#xff0c;介绍参数解析器。本文讨论的参数解析表示从HTTP消息中解析出JAVA对象或流对象并传参给Controller接口的过程。 本文内容包括介绍参数解析器工作原理、常见的参数解析器、自定义参数解析器等三部分。其中&#xff0…