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);

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

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

相关文章

Stable Diffusion的解读(一)

Stable Diffusion的解读&#xff08;一&#xff09; 文章目录 Stable Diffusion的解读&#xff08;一&#xff09;摘要Abstract一、机器学习部分1. Stable Diffusion的早期工作1.1 从编码器谈起1.2 第一条路线&#xff1a;VAE和DDPM1.3 第二条路线&#xff1a;VQVAE1.4 路线的交…

计算机网络——TCP篇

TCP篇 基本认知 TCP和UDP的区别? TCP 和 UDP 可以使用同一个端口吗&#xff1f; 可以的 传输层中 TCP 和 UDP在内核中是两个完全独立的软件模块。可以根据协议字段来选择不同的模块来处理。 TCP 连接建立 TCP 三次握手过程是怎样的&#xff1f; 一次握手:客户端发送带有 …

ROS话题通信机制理论模型的学习

话题通信是ROS&#xff08;Robot Operating System&#xff0c;机器人操作系统&#xff09;中使用频率最高的一种通信模式&#xff0c;其实现模型主要基于发布/订阅模式。 一、基本概念 话题通信模型中涉及三个主要角色&#xff1a; ROS Master&#xff08;管理者&#xff0…

【Android】名不符实的Window类

1.“名不符实”的Window类 Window 是一个窗口的概念&#xff0c;是所有视图的载体&#xff0c;不管是 Activity&#xff0c;Dialog&#xff0c;还是 Toast&#xff0c;他们的视图都是附加在 Window 上面的。例如在桌面显示一个悬浮窗&#xff0c;就需要用到 Window 来实现。Wi…

后端java——如何为你的网页设置一个验证码

目录 1、工具的准备 2.基本方法 3.实现类 4.实践 HTML文件&#xff1a; Java文件1:创建验证码 Java文件2:验证验证码 本文通过HUTOOL实现&#xff1a;Hutool参考文档Hutool&#xff0c;Java工具集https://hutool.cn/docs/#/ 1、工具的准备 如果我们通过hutool来实现这个…

【go从零单排】Strings and Runes 字符串和字符

Don’t worry , just coding! 内耗与overthinking只会削弱你的精力&#xff0c;虚度你的光阴&#xff0c;每天迈出一小步&#xff0c;回头时发现已经走了很远。 概念 在Go语言中&#xff0c;rune 是一个内置的数据类型&#xff0c;用于表示一个Unicode字符。它实际上是一个别名…

如何在本地Linux服务器搭建WordPress网站结合内网穿透随时随地可访问

文章目录 前言1. 安装WordPress2. 创建WordPress数据库3. 安装相对URL插件4. 安装内网穿透发布网站4.1 命令行方式&#xff1a;4.2. 配置wordpress公网地址 5. 配置WordPress固定公网地址 前言 本文主要介绍如何在Linux Ubuntu系统上使用WordPress搭建一个本地网站&#xff0c…

vue data变量之间相互赋值或进行数据联动

摘要&#xff1a; 使用vue时开发会用到data中是数据是相互驱动&#xff0c;经常会想到watch,computed&#xff0c;总结一下&#xff01; 直接赋值&#xff1a; 在 data 函数中定义的变量可以直接在方法中进行赋值。 export default {data() {return {a: 1,b: 2};},methods: {u…

在 Java 中使用脚本语言

在 Java 中使用脚本语言&#xff0c;特别是在 Java 平台上集成如 Python、JavaScript 或 Ruby 等语言&#xff0c;通常可以通过 Java 的 Scripting API 来实现。这个 API 基于 JSR 223&#xff08;“Scripting for the Java Platform”&#xff09;&#xff0c;提供了一种标准方…

大数据-212 数据挖掘 机器学习理论 - 无监督学习算法 KMeans 基本原理 簇内误差平方和

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

微服务系列六:分布式事务与seata

目录 实验环境说明 前言 一、分布式事务问题与策略 1.1 分布式事务介绍 1.2 分布式事务解决策略分析 二、分布式事务解决方案 Seata 2.1 认识Seata 2.2 Seata的工作原理 2.3 部署Seata微服务 2.3.1 准备数据库表 2.3.2 准备配置文件 2.3.3 docker部署 2.4 微服务集…

Java 上机实践2(基础数据类型与数组)

&#xff08;大家好&#xff0c;今天分享的是Java的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 实验一&#xff1a;输出希腊字母表 一、实验目的 二、实验要求 三、程序代码 四、实验结果 实验二&#xff1a;…

w024基于SpringBoot的企业客户管理系统的设计与实现

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0…

并发编程volatile精解

多线程下变量的不可见性 在多线程并发执行的情况下&#xff0c;多个线程修改共享的成员变量&#xff0c;会出现一个线程修改了共享变量的值后&#xff0c;另一个线程不能直接看到该线程修改后的变量最新值。(多线程下修改共享变量会出现变量修改值后的不可见性) 可见性问题…

十款外贸软件盘点,专注企业订单业务管理

在当今全球化的市场环境中&#xff0c;外贸企业的发展面临着诸多挑战与机遇。如何高效管理企业业务&#xff0c;提升运营效率&#xff0c;成为外贸企业在激烈竞争中脱颖而出的关键。外贸业务管理ERP软件作为一种强大的工具&#xff0c;能够整合企业资源、优化管理流程、实现数据…

yaml文件编写

Kubernetes 支持YAML和JSON格式管理资源 JSON 格式:主要用于 api 接口之间消息的传递 YAML 格式;用于配置和管理,YAML是一种简洁的非标记性语言,内容格式人性化容易读懂 一&#xff0c;yaml语法格式 1.1 基本语法规则 使用空格进行缩进&#xff08;不使用制表符&#xff0…

Node.js 全栈开发进阶篇

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;node.js篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来node.js篇专栏内容:node.js- 全栈开发进阶篇 前言 大家好&#xff0c;我是青山。在上一篇文章中&#xff0c;…

Vue(JavaScript)读取csv表格并求某一列之和(大浮点数处理: decimal.js)

文章目录 想要读这个表格&#xff0c;并且求第二列所有价格的和方法一&#xff1a;通过添加文件输入元素上传csv完整&#xff08;正确&#xff09;代码之前的错误部分因为价格是小数&#xff0c;所以下面的代码出错。如果把parseFloat改成parseInt&#xff0c;那么求和没有意义…

C语言初阶必会的练习题(3)之位操作符(^ 、、>>等)的应用

C语言初阶必会的练习题&#xff08;3&#xff09; 放在最前面的1、不允许创建临时变量&#xff0c;交换两个整数的内容1.1、分析&#xff1a;见代码注释&#xff08;a&#xff09;方法 1&#xff08;b&#xff09;方法 2 1.2、结果展示方法 1 的 结果&#xff1a;方法 2 的 结果…

基于SSM框架的乡村农户对口扶贫系统

基于SSM框架的乡村农户对口扶贫系统。 设计步骤&#xff1a; 项目架构创建&#xff1a;首先创建项目的基本架构&#xff0c;包括com.zc.xxx路径下的文件和resources资源文件夹。 SSM架构&#xff1a;使用Spring、SpringMVC、MyBatis作为后端架构&#xff0c;采用POJO—Dao—…