day-07 I/O复用(select)

news2024/11/29 14:53:31

一.I/O复用

(一)基于I/O复用的服务器端

1.多进程服务器

        每次服务都需要创建一个进程,需要大量的运算和内存空间

2.复用

        只需创建一个进程。

3.复用技术在服务器端的应用

 (二)select函数实现服务器端

  • (Linux和Windows平台下均有select函数,所以具有良好移植性)

1.select函数调用过程:

2.select函数示例:(5秒内控制才没有输入,就输出 Timeout ;否则打印输入。)

#include<iostream>
#include<unistd.h>
#include<sys/time.h>
#include<sys/select.h>
using namespace std;
#define BUF_SIZE 30

int main(int argc,char *argv[]){
	fd_set reads,temps;
	int result,str_len;//fd_set类型是一个文件描述符集合,
	char buf[BUF_SIZE];//在这里声明了reads和temps两个集合用于I/O复用。
	struct timeval timeout;

	FD_ZERO(&reads);//用于清空文件描述符集合。
	FD_SET(0,&reads);//将标准输入文件描述符添加到集合中

	while(1){
		temps=reads;//在每次循环开始时,将temps设置为上一次存有文件描述符的集合reads的副本。
		timeout.tv_sec=5;//设置超时时间为5秒
		timeout.tv_usec=0;
		result=select(1,&temps,0,0,&timeout);调用select函数来等待可读事件就绪或超时发生。
		if(result==-1){//第一个参数表示要监视的最大文件描述符值加1,
			cout<<"select() error"<<endl;//第二个参数是指向待检查的文件描述符集合的指针,
			break;                       //后面的三个参数是输出参数。
		}
		else if(result==0)
			cout<<"Time out"<<endl;
		else{
			if(FD_ISSET(0,&temps))//检查输入文件描述符是否就绪
			{
				str_len=read(0,buf,BUF_SIZE);
	                        buf[str_len]=0;
                	        cout<<"message from console: "<<buf<<endl;
			}
		}
        //如果select函数返回-1,表示出现了错误,输出错误信息并跳出循环。
        //如果select函数返回0,表示超时,输出"Time out"。
        //如果select函数返回大于0的值,表示文件描述符就绪。
        //这里通过FD_ISSET宏检查标准输入文件描述符是否在集合中就绪。
        //如果标准输入文件描述符就绪,调用read函数读取输入内容,并输出到控制台。

		
	}
	return 0;
}

3.实现I/O复用服务器端

#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<sys/time.h>
#include<sys/select.h>
using namespace std;

#define BUF_SIZE 100//宏定义了一个缓冲区大小为100的常量。
void error_handling(const  char *buf);

int main(int argc,char *argv[]){
	int serv_sock,clnt_sock;
	struct sockaddr_in serv_adr,clnt_adr;
	struct timeval timeout;
	fd_set reads,cpy_reads;

	socklen_t adr_sz;
	int fd_max,str_len,fd_num,i;
	char buf[BUF_SIZE];
	if(argc!=2){
		cout<<"Usage:"<<argv[0]<<endl;
		exit(1);
	}

	serv_sock=socket(PF_INET,SOCK_STREAM,0);//创建套接字
	memset(&serv_adr,0,sizeof(serv_adr));//将结构体清零
	serv_adr.sin_family=AF_INET;
	serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);//设置服务器地址信息、IP地址和端口号
	serv_adr.sin_port=htons(atoi(argv[1]));

	if(bind(serv_sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr))==-1)
		error_handling("bind() error");      //将套接字和指定地址绑定
	if(listen(serv_sock,5)==-1)//开始监听连接请求
		error_handling("listen() error");

	FD_ZERO(&reads);//清空文件描述符集合
	FD_SET(serv_sock,&reads);//将服务器套接字添加到reads集合中
	fd_max=serv_sock;//fd_max初始化为服务器套接字的值

	while(1){//进入主循环
		cpy_reads=reads;//将reads集合复制过来
		timeout.tv_sec=5;//超时时间
		timeout.tv_usec=5000;

		if((fd_num=select(fd_max+1,&cpy_reads,0,0,&timeout))==-1)
			break;        //监控文件描述符的状态变化
		if(fd_num==0)
			continue;

		for(i=0;i<fd_max+1;i++){
			if(FD_ISSET(i,&cpy_reads)){//检查文件描述符是否就绪
				if(i==serv_sock){//如果是服务器套接字,表示有新的客户端连接请求
					adr_sz=sizeof(clnt_adr);
					clnt_sock=
						accept(serv_sock,(struct sockaddr*)&clnt_adr,&adr_sz);
					FD_SET(clnt_sock,&reads);
					if(fd_max<clnt_sock)
						fd_max=clnt_sock;
					cout<<"connect client: "<<clnt_sock<<endl;
				}
				else{//如果不是服务器套接字,表示已连接的客户端有数据发送过来
					str_len=read(i,buf,BUF_SIZE);
					if(str_len==0){
						FD_CLR(i,&reads);
						close(i);
						cout<<"closed client:"<<i<<endl;
					}
					else
						write(i,buf,str_len);

				}
			}
		}
	}
	close(serv_sock);
	return 0;
}

void error_handling(const char *buf){
	cout<<buf<<endl;
	exit(1);
}

(三)总结 

1.请解释复用技术的通用含义,并说明何为I/O复用。

复用技术指为了提高物理设备的效率,用最少的物理要素传递最多数据时使用的技术。同样,I/O复用是指将需要I/O的套接字捆绑在一起,利用最少限度的资源来收发数据的技术

2.多进程并发服务器的缺点有哪些?如何在I/O复用服务器端中弥补?

多进程并发服务器的服务方式是,每当客户端提出连接要求时,就会追加生成进程。但构建进程是一项非常有负担的工作,因此,向众多客户端提供服务存在一定的局限性。而复用服务器则是将套接字的文件描述符捆绑在一起管理的方式,因此可以一个进程管理所有的I/O操作

3.select函数的观察对象中应包含服务器端套接字(监听套接字),那么应将其包含到哪一类监听对象集合?请说明原因

服务器套接字的作用是监听有无连接请求,即判断接收的连接请求是否存在?应该将其包含到“读”类监听对象的集合中。

4.select函数使用的fd_set结构体在Windows和Linux中具有不同的声明。请说明却别,同时解释存在区别的必然性

Linux的文件描述符从0开始递增,因此可以找出当前文件描述符数量和最后生成的文件描述符之间的关系。但Windows的套接字句柄并非从0开始,并且句柄的整数值之间并无规律可循,因此需要直接保存句柄的数组和记录句柄数的变量。

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

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

相关文章

JVM学习(四)--内存问题分析思路

linux获取jvm当前dump文件 命令行为&#xff1a;jmap -dump:file[文件名] [pid] 然后等待生成dump文件&#xff0c;生成的dump文件就在当前目录下。如下图&#xff1a; 然后就可以下载到本地&#xff0c;用本地jdk里自带的jvisualvm来解析文件。 在用本地的jvisualvm解析之前…

uniapp 微信小程序 获取用户头像和昵称

一、背景 自2022年10月25日后&#xff0c;小程序 wx.getUserProfile 接口 被收回&#xff0c;通过 wx.getUserInfo 接口获取用户头像将统一返回默认灰色头像&#xff0c;昵称将统一返回 “微信用户”。如需获取用户头像昵称&#xff0c;可以手动获取&#xff0c;具体步骤&…

七、性能测试之内存分析

性能测试之内存分析与实战 一、内存知识1、理解&#xff1a;2、内存的组成&#xff1a;内存地址、存储单元3、内存---树形结构1、链表2、二叉树 4、数据结构 二、内存使用1、典型案例&#xff1a;JVM&#xff08;java虚拟机&#xff09;包含程序计数器&#xff0c;java虚拟机栈…

探索图像数据中的隐藏信息:语义实体识别和关系抽取的奇妙之旅

探索图像数据中的隐藏信息&#xff1a;语义实体识别和关系抽取的奇妙之旅 1. 简介 1.1 背景 关键信息抽取 (Key Information Extraction, KIE)指的是是从文本或者图像中&#xff0c;抽取出关键的信息。针对文档图像的关键信息抽取任务作为OCR的下游任务&#xff0c;存在非常…

LNMP架构:搭建Discuz论坛

文章目录 1. 编译安装Nginx1.1 前置准备1.2 编译安装1.3 添加nginx系统服务 2.编译安装MySql2.1 前置准备2.2 编译安装2.3 修改mysql 配置文件2.4 设置路径环境变量2.5 初始化数据库2.6 添加musql系统服务2.7 修改MySql登录密码 3. 编译安装PHP3.1 前置准备3.2 编译安装3.3 复制…

【前端demo】倒计时器 可选择时间 原生实现

文章目录 效果过程日历与获取时间居中背景与字计时器清空计时器 代码HTMLCSSJS 其他demo 效果 效果预览&#xff1a;倒计时器 可选择时间 (codepen.io) 参考&#xff1a; Simple Clock/Countdown timer (codepen.io) 前端页面实现倒计时效果的几种方法_前端倒计时__Boboy的…

安卓逆向 - Frida反调试绕过

本文仅供学习交流&#xff0c;只提供关键思路不会给出完整代码&#xff0c;严禁用于非法用途&#xff0c;谢绝转载&#xff0c;若有侵权请联系我删除&#xff01; 本文案例 app&#xff1a;5Lqs5LicYXBwMTEuMy4y 一、引言&#xff1a; Frida是非常优秀的一款 Hook框架&#…

iperf 测试网络性能

Iperf 是一个网络性能测试工具。Iperf可以测试最大TCP和UDP带宽性能&#xff0c;具有多种参数和UDP特性&#xff0c;可以根据需要调整&#xff0c;可以报告带宽、延迟抖动和数据包丢失。 官网&#xff1a;iperf.fr https://iperf.fr 支持参数 参数说明-p, --port #Server 端监…

设计模式入门(二)观察者模式

设计模式入门 本系列所有内容参考自《HeadFirst设计模式》。因为书中的代码是采用java语言写的&#xff0c;博主这里用C语言改写。 这里采用讲故事的方式进行讲解。若有错误之处&#xff0c;非常欢迎大家指导。 设计模式&#xff1a;模式不是代码&#xff0c;而针对设计问题的…

A Mathematical Framework for Transformer Circuits—Part (1)

A Mathematical Framework for Transformer Circuits 前言Summary of ResultsREVERSE ENGINEERING RESULTSCONCEPTUAL TAKE-AWAYS Transformer OverviewModel SimplificationsHigh-Level ArchitectureVirtual Weights and the Residual Stream as a Communication ChannelVIRTU…

用树形dp+状压维护树上操作的计数问题:0902T3

发现操作数 k ≤ 6 k\le6 k≤6&#xff0c;可以考虑对操作进行状压。 然后找找性质&#xff0c;发现要么删掉一棵子树&#xff0c;要么进去该子树。可以视为每种操作有两种情况。 然后分讨一下当前该如何转移。 树形dp的顺序&#xff1a; 合并子树考虑当前往上的边的方向 …

自定义类型:结构体、枚举、联合

目录 结构体 结构体的基础知识 结构的声明 特殊的声明 结构体的自引用 结构体变量的定义和初始化 结构体内存对齐 修改默认对齐数 结构体传参 位段 什么是位段 位段的内存分配 位段的跨平台问题 位段的应用 枚举 枚举类型的定义 枚举的优点 联合体&#xff08;共…

Mysql创建用户并且给指定用户添加某个库的所有权限

注意&#xff1a; 运行以下命令首先运行的用户需要有以下操作权限才可以执行 创建用户 创建用户&#xff1a;命令中的’username’替换为您要创建的用户名&#xff0c;‘host’替换为用户的主机名或IP地址如果都可以访问则配置’%&#xff0c;password’替换为用户的密码 CRE…

WoW GM

当年黑翼被人黑G以后&#xff0c;后来我就自己开团&#xff0c;今天整理电脑还发现截图。。。。

AI绘画:StableDiffusion实操教程-斗罗大陆2-江楠楠-常服(附高清图下载)

前段时间我分享了StableDiffusion的非常完整的教程&#xff1a;“AI绘画&#xff1a;Stable Diffusion 终极宝典&#xff1a;从入门到精通 ” 尽管如此&#xff0c;还有读者反馈说&#xff0c;尽管已经成功安装&#xff0c;但生成的图片与我展示的结果相去甚远。真实感和质感之…

h5页面使用js注入企业微信sdk

let script document.createElement(script); //定义script标签 script.type text/javascript; script.src http://res.wx.qq.com/open/js/jweixin-1.2.0.js; document.getElementsByTagName(body)[0].appendChild(script); //将script标签插入到body下面

ISO/IEC标准组织介绍(三十七)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…

[论文笔记]SiameseNet

引言 这是Learning Text Similarity with Siamese Recurrent Networks的论文笔记。 论文标题意思是利用孪生循环神经网络学习文本相似性。 什么是孪生神经网络呢?满足以下两个条件即可: 输入是成对的网络结构和参数共享(即同一个网络)如下图所示: 看到这种图要知道可能代…

C语言:截断+整型提升+算数转换练习

详情关于整型提升、算数转换与截断见文章&#xff1a; 《C语言&#xff1a;整型提升》 《C语言&#xff1a;算数转换》 一、代码一 int main() { char a -1; signed char b -1; unsigned char c -1; printf("%d %d %d", a, b, c); return 0; } 求…

mp代码生成插件

mp代码生成插件 1.下载下面的插件 2.连接测试 3.生成代码的配置 4.生成代码 红色的是刚刚生成的。 我觉得不如官方的那个好用&#xff0c;唯一的好处就是勾选的选项能够看的懂得。