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的事务&…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...
[特殊字符] 手撸 Redis 互斥锁那些坑
📖 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作,想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁,也顺便跟 Redisson 的 RLock 机制对比了下,记录一波,别踩我踩过…...
