Webserver(4.6)poll和epoll
目录
- poll
- client.c
- poll.c
- epoll
- epoll.c
- client.c
- epoll的两种工作模式
- 水平触发
- 边沿触发
poll
poll是对select的一个改进
select的缺点在于每次都需要将fd集合从用户态拷贝到内核态,开销很大。每次调用select都需要在内核遍历传递进来的所有fd,这个开销也很大。select支持的文件描述符数量太小了,默认是1024。fds集合不能重用,每次都需要重置。
使用内核中的文件描述符在进行交互
client.c
#include<stdio.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>int main(){//1.创建套接字int fd=socket(AF_INET,SOCK_STREAM,0);if(fd==-1){perror("socket");exit(-1);}//2.连接服务器端struct sockaddr_in serveraddr;serveraddr.sin_family=AF_INET;inet_pton(AF_INET,"127.0.0.1",&serveraddr.sin_addr.s_addr);serveraddr.sin_port=htons(9999);int ret=connect(fd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));if(ret==-1){perror("connect");exit(-1);}//3.通信int num=0;while(1){char sendBuf[1024]={0};sprintf(sendBuf,"send data %d",num++);sleep(1);//给服务器发送数据write(fd,sendBuf,strlen(sendBuf)+1);int len=read(fd,sendBuf,sizeof(sendBuf));if(len==-1){perror("read");exit(-1);}else if(len>0){printf("recv server data:%s\n",sendBuf);}else if(len==0){//表示客户端断开连接printf("server closed...");}}//关闭连接close(fd);return 0;
}
poll.c
#include<stdio.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/time.h>
#include<sys/types.h>
#include<sys/select.h>
#include<poll.h>int main(){//创建socketint lfd=socket(PF_INET,SOCK_STREAM,0);struct sockaddr_in saddr;saddr.sin_port=htons(9999);saddr.sin_family=AF_INET;saddr.sin_addr.s_addr=INADDR_ANY;//绑定bind(lfd,(struct sockaddr *)&saddr,sizeof(saddr));//监听listen(lfd,8);//初始化检测的文件描述符数组struct pollfd fds[1024];for(int i=0;i<1024;i++){fds[i].fd=-1;fds[i].events=POLLIN;}fds[0].fd=lfd;int nfds=0;while(1){//调用poll系统函数,让内核帮检测哪些文件描述符有数据int ret=poll(fds,nfds+1,-1);if(ret==-1){perror("poll");exit(-1);}else if(ret==0){continue;}else if(ret>0){//说明检测到了有文件描述符的对应的缓冲区的数据发生了改变if(fds[0].revents&POLLIN){//表示有新的客户端连接进来了struct sockaddr_in cliaddr;int len=sizeof(cliaddr);int cfd=accept(lfd,(struct sockaddr *)&cliaddr,&len);//将新的文件描述符加入到集合中for(int i=1;i<1024;i++){if(fds[i].fd==-1){fds[i].fd=cfd;fds[i].events=POLLIN;break;}}//更新最大的文件描述符nfds=nfds>cfd? nfds:cfd;}for(int i=1;i<=nfds;i++){if(fds[i].revents&POLLIN){//说明这个文件描述符对应的客户端发来了数据char buf[1024]={0};int len=read(fds[i].fd,buf,sizeof(buf));if(len==-1){perror("read");exit(-1);}else if(len==0){printf("client closed..\n");close(fds[i].fd);fds[i].fd=-1;}else if(len>0){printf("read buf:%s\n",buf);write(fds[i].fd,buf,strlen(buf)+1);}}}}}close(lfd);return 0;
}
epoll
poll就是扩充了select的大小,用一个结构体集合去取代了这个集合
epoll.c
#include<stdio.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/time.h>
#include<sys/types.h>
#include<sys/epoll.h>int main(){//创建socketint lfd=socket(PF_INET,SOCK_STREAM,0);struct sockaddr_in saddr;saddr.sin_port=htons(9999);saddr.sin_family=AF_INET;saddr.sin_addr.s_addr=INADDR_ANY;//绑定bind(lfd,(struct sockaddr *)&saddr,sizeof(saddr));//监听listen(lfd,8);//调用epoll来创建一个epoll实例int epfd=epoll_create(100);//将监听的文件描述符相关的检测信息添加到epoll实例中struct epoll_event epev;epev.events=EPOLLIN;epev.data.fd=lfd;epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&epev);struct epoll_event epevs[1024];//用于接收监测后的数据,内核会返回进来while(1){int ret=epoll_wait(epfd,epevs,1024,-1);if(ret==-1){perror("epoll_wait");exit(-1);}printf("ret=%d\n",ret);for(int i=0;i<ret;i++){int curfd=epevs[i].data.fd;if(curfd==lfd){//监听的文件描述符有数据到达,即有客户端连接。客户端连接的信息都在lfd中//表示有新的客户端连接进来了struct sockaddr_in cliaddr;int len=sizeof(cliaddr);int cfd=accept(lfd,(struct sockaddr *)&cliaddr,&len);epev.events=EPOLLIN | EPOLLOUT;epev.data.fd=cfd;epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&epev);//accept得到的文件描述符添加到epfd这个实例中}else { //有数据到达,需要通信,说明不是监听的文件描述符。因为返回的是监听描述符说明是客户端连接,返回其他的文件描述符说明有数据到达。if(epevs[i].events&EPOLLOUT){continue;}//说明有数据到达,需要通信char buf[1024]={0};int len=read(curfd,buf,sizeof(buf));if(len==-1){perror("read");exit(-1);}else if(len==0){printf("client closed..\n");epoll_ctl(epfd,EPOLL_CTL_DEL,curfd,NULL);close(curfd);}else if(len>0){printf("read buf:%s\n",buf);write(curfd,buf,strlen(buf)+1);}}}}close(lfd);close(epfd);return 0;
}
client.c
#include<stdio.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>int main(){//1.创建套接字int fd=socket(AF_INET,SOCK_STREAM,0);if(fd==-1){perror("socket");exit(-1);}//2.连接服务器端struct sockaddr_in serveraddr;serveraddr.sin_family=AF_INET;inet_pton(AF_INET,"127.0.0.1",&serveraddr.sin_addr.s_addr);serveraddr.sin_port=htons(9999);int ret=connect(fd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));if(ret==-1){perror("connect");exit(-1);}//3.通信int num=0;while(1){char sendBuf[1024]={0};sprintf(sendBuf,"send data %d",num++);usleep(1000);//给服务器发送数据write(fd,sendBuf,strlen(sendBuf)+1);int len=read(fd,sendBuf,sizeof(sendBuf));if(len==-1){perror("read");exit(-1);}else if(len>0){printf("recv server data:%s\n",sendBuf);}else if(len==0){//表示客户端断开连接printf("server closed...");}}//关闭连接close(fd);return 0;
}
epoll的两种工作模式
水平触发
服务器一次只能读5个数据
客户端用键盘录入的方式发送信息
数据没有读完的话会一直通知,这是水平触发模式,直到读完为止
边沿触发
设置边沿触发
只收到了hello
但是再输入一次,会返回nihao,像挤牙膏一样一点一点得到缓冲区的数据
阻塞缓冲区
通过一个循环读取和非阻塞文件描述符,可以一次性读取
//循环读取出所有数据char buf[5];int len=0;while((len=read(curfd,buf,sizeof(buf))>0)){//将read设置为非阻塞,不然会堵在这出不来,就接收不了epoll_wait更新的情况//打印数据printf("recv data:%s\n",buf);write(curfd,buf,len);}if(len==0){printf("client closed...\n");}else if(len==-1){perror("read");exit(-1);}
//设置cfd为非阻塞int flag=fcntl(cfd,F_GETFL);flag | O_NONBLOCK;fcntl(cfd,F_SETFL,flag);
相关文章:

Webserver(4.6)poll和epoll
目录 pollclient.cpoll.c epollepoll.cclient.c epoll的两种工作模式水平触发边沿触发 poll poll是对select的一个改进 select的缺点在于每次都需要将fd集合从用户态拷贝到内核态,开销很大。每次调用select都需要在内核遍历传递进来的所有fd,这个开销也…...

LVGL 与 QT
LVGL 与 QT LVGL 适用于嵌入式、资源受限设备,尤其是在需要高效图形渲染和小型显示屏的场景下非常合适。它具有轻量级、模块化的特点,适用于内存和计算能力有限的硬件。 Qt 是一个功能强大的跨平台框架,适合开发桌面应用以及较为复杂的嵌入式…...

如何选择最适合的项目管理软件?2024年大厂首选7款工具盘点
选择最适合的项目管理软件对于提升团队效率、优化工作流程至关重要。2024年,各大厂在项目管理上逐渐趋向于使用更加智能化、集成化和协作性的工具。以下是如何选择最适合的项目管理软件,并对2024年大厂首选工具进行盘点。 选择适合的项目管理软件的关键…...

【数据结构】选择排序——选择排序 和 堆排序
选择排序 和 堆排序 一、选择排序选择排序的思路及其代码选择排序的弊端 二、堆排序三、速度对比同时排10000个数同时排100000个数同时拍500000个数堆排 1 亿个数 一、选择排序 选择排序的思路及其代码 选择排序思路很简单 就是经过将数组遍历选择最小值 将最小值位置的数与数…...

P11229 [CSP-J 2024] 小木棍
[CSP-J 2024] 小木棍 题目描述 小 S 喜欢收集小木棍。在收集了 n n n 根长度相等的小木棍之后,他闲来无事,便用它们拼起了数字。用小木棍拼每种数字的方法如下图所示。 现在小 S 希望拼出一个正整数,满足如下条件: 拼出这个数…...

【学习笔记】SAP ABAP——OPEN SQL(一)【SELECT语句】
SELECT语句简介 SELECT <lines> <columns> FROM <db> WHERE <condition>其中代表查询的件数,代表查询的字段名 SELECT SINGLE SELECT SINGLE <cols> FROM <db> WHERE <condition>该语句用于从数据库表中查询单条数据 …...

SQL注入(1)
1.数字型注入 例如PHP代码 “ Select username from users where id”.$_GET[id] 可以注意到,用户的输入ID字段没有任何过滤的,被直接拼接在了SQL查询语句中,由于ID没有被引号包裹ÿ…...

在AI时代,如何解决人的工作岗位被AI替代的问题?
在AI时代,工作岗位被AI替代的问题确实是一个重要的社会课题。随着技术的不断进步,许多传统的工作变得自动化,这带来了效率的提升,但也引发了就业方面的挑战。要应对这一问题,我们可以从以下几方面入手: 促进…...

Linux命令--paste
简介 paste命令用于合并文件行 参数说明 -d: 自定义间隔符,默认为tab -s:串行处理,非并行 示例 将两个文件,按照行合并 demo1.conf内容如下: name domain ip area user password roledemo2.conf内容如下 test t…...

数据结构模拟题[九]
数据结构试卷(九) 一、选择题 (30 分) 1.下列程序段的时间复杂度为( )。 for(i0 ; i<m ; i) for(j0 ; j<t ; j) c[i][j]0 ; for(i0 ; i…...

2024年10月国产数据库大事记-墨天轮
本文为墨天轮社区整理的2024年10月国产数据库大事件和重要产品发布消息。 目录 2024年10月国产数据库大事记 TOP102024年10月国产数据库大事记(时间线)产品/版本发布代表厂商大事记信创数据库上市公司2024年Q3财报 达梦数据:2024年前三季度…...

Andon 业务流程业务开发陷阱----从真实用户与管理者视角逻辑差异
Q : Andon 问题识别归类(就是问题的3层细化),是在事中,还是在事后? A : 不存在事中就细化归类,有悖于生产问题解决流程。 从操作员的角度来看,他们在事中可能只能识别出存在质量问题,但无法进行具体的质量问题编号…...

Python闭包|你应该知道的常见用例(上)
引言 在 Python 编程语言中,闭包通常指的是一个嵌套函数,即在一个函数内部定义的另一个函数。这个嵌套的函数能够访问并保留其外部函数作用域中的变量。这种结构就构成了一个闭包。 闭包在函数式编程语言中非常普遍。在 Python 中,闭包特别有…...

printf影响单片机中断速度
printf是我们常用的调试程序的手段,在第一版程序中,经常会使用printf来验证程序是否工作正确。这样的调试手段应该在正式版的程序发布前注释掉或者删除。而且不当地使用printf也会带来某些功能性问题,例如,在某项目中,…...

JavaScript 23种经典设计模式简介
23种JavaScript经典设计模式 JavaScript经典设计模式 通过之前的学习,我们知道设计模式是一种解决代码组织、代码复用和代码可维护性等问题的技术方法。它通过将代码以特定的方式组织起来,使代码结构更加清晰、可读性更高、易于维护和扩展。为了在开发…...

位运算相关算法
一、异或运算介绍 1、性质介绍 异或运算(XOR,Exclusive OR)是一种位运算符。对于两个位进行异或操作,当且仅当这两个位不同时,结果为 1;如果相同,则结果为 0。 A B A^B00001 1 101110 任何数…...

解决:无法在此设备上激活Windows因为无法连接到你的组织的激活服务器
问题: 桌面右下角会出现这个东西👇 在设置里查看激活状态就会看到👇 解决方法 : 1.打开CMD 搜索CMD,然后以管理员身份运行 2.设置 KMS服务器 1)命令行输入: slmgr /skms kms.03k.org 然后…...

【Spring】——SpringBoot项目创建
阿华代码,不是逆风,就是我疯 你们的点赞收藏是我前进最大的动力!! 希望本文内容能够帮助到你!! 目录 引入 一:介绍 二:Spring Boot项目创建 0:项目目录 1:…...

聊一聊:ChatGPT搜索引擎会取代谷歌和百度吗?
当地时间 10 月 31 日,OpenAI 正式推出了 ChatGPT 搜索功能,能实时、快速获取附带相关网页来源链接的答案。这一重大升级标志着其正式向谷歌的搜索引擎霸主地位发起挑战。 本周五我们聊一聊: 欢迎在评论区畅所欲言,分享你的观点~ …...

分布式中常见的问题及其解决办法
分布式中常见的问题及其解决办法 一、多个微服务要操作同一个存储在redis中的变量,如何确保这个变量的正确性 答: 在多个微服务操作同一个存储在Redis中的变量时,可以采取以下措施来确保变量的正确性: 1、使用Redis的事务&…...

HTML 基础标签——多媒体标签<img>、<object> 与 <embed>
文章目录 1. `<img>` 标签主要属性示例注意事项2. `<object>` 标签概述主要属性示例注意事项3. `<embed>` 标签概述主要属性示例注意事项小结在现代网页设计中,多媒体内容的使用变得越来越重要,因为它能够有效增强用户体验、吸引注意力并传达信息。HTML 提…...

word mathml 创建粗体字母快捷键
在 mathml 中达到latex中 \mathbf{A} 的效果 由于word本身不支持这个命令,所以打算用快捷键实现 快捷键的功能是加粗光标前一个字目 1. Alt F8 打开宏,如果打不开可以尝试 Alt Fn F8 2. 输入 BoldPreviousCharacter 新建宏: Sub Bold…...

ROOT添加用户提示权限不够
有个系统已经上线过了,之后测评整改要求不能用root启动中间件,我就想着添加一个普通用户,赋予指定目录权限,然后启动应用就行了 。 结果用root用户创建账号提示权限不够,确认了几遍,是root 命令前面加sud…...

关于使用svgIcon 菜单折叠 显示文字情况
使用的工具:vue2,ant design vue 问题: **解决:在<svg-icon> 外面包一层 <a-icon> ** 使用: 在 main.js 中:...

Python使用PDF相关组件案例详解
主要对pdfminer.six、pdfplumber、PyMuPDF、PyPDF2、PyPDF4、pdf2image、camelot-py七个PDF相关组件分别详解,具体使用案例演示 1. pdfminer.six pdfminer.six 是一个专门用来从 PDF 中提取文本的库,能够处理复杂的文本布局,适合用于文本解析…...

day53 图论章节刷题Part05(并查集理论基础、寻找存在的路径)
并查集理论基础 基础内容 并查集常用来解决连通性问题,主要有两个功能: 将两个元素添加到一个集合中判断两个元素在不在同一个集合 将三个元素A,B,C (分别是数字)放在同一个集合,其实就是将…...

鸿蒙next选择 Flutter 开发跨平台应用的原因
在移动操作系统的竞争中,鸿蒙(HarmonyOS)自从发布以来便吸引了广泛的关注。作为华为主导的操作系统,鸿蒙的设计初衷是打破平台壁垒,实现设备间的无缝连接与应用共享。然而,要实现这一目标,仅仅依…...

shodan6-7---清风
shodan6-7 1.shodan网页版 以cve-2019-0708漏洞指纹特征为例 "\x03\x00\x00\x0b\x06\xd0\x00\x00\x124\x00"在这里插入图片描述 搜索命令参考 https://www.shodan.io/search/filters这个网页中有搜索关键词 对指定网址进行监控,这里可以对ip进行扫描&…...

FTP、ISCSI、CHRONY、DNS、NFS、DOCKER、MARIADB、NGINX、PHP、CA各服务开启方法
2.1 FTP 服务 (vsftpd) 安装 vsftpd: sudo yum install vsftpd -y 启动并设置开机自启: sudo systemctl start vsftpdsudo systemctl enable vsftpd 配置文件位于 /etc/vsftpd/vsftpd.conf,可根据需要修改配置。 2.2 SCSI 服务 SCSI 配…...

抢先体验AI领域的新宠儿:Llama3.1,部署实战探索!
本文简介 就在今天,Meta 发布了 Llama 3.1,这次带来的中杯、大杯和超大杯3个版本。 从纸面数据来看,Llama 3.1 超大杯已经能跟 GPT-4 Omni、Claude 3.5 Sonnet 分庭抗礼了。 而中杯和大杯更是将同量级的对手摁在地上摩擦。 要知道ÿ…...