当前位置: 首页 > news >正文

linux网络编程 | c | epoll实现IO多路转接服务器

epoll实现IO多路转接服务器

可通过以下视频学习

06-opell函数实现的多路IO转接_哔哩哔哩_bilibili

通过响应式–多路IO转接实现

文章目录

  • epoll实现IO多路转接服务器
    • 1.思路&功能
      • 核心思路
    • 2.代码实现
      • multi_epoll_sever.c
      • 运行图

1.思路&功能

**功能:**客户端输入小写字符串,服务器转成大写返回给客户端

思路:

核心思路

  1. socket()、bind()、listen()
  2. epoll_create创建红黑树,它的返回值就是树的根节点
  3. epoll_ctl将listenfd添加到树上
  4. 循环epoll_wait进行监听,它的返回值是满足监听的总个数,所以以它的返回值为遍历上限去判断事件
  5. 如果它返回的数组中data.fd等于lfd,那么就accept去连接客户端 并将新的cfd加入树中
  6. 如果不是lfd,就说明有读事件发生,就去判断读到的返回值,<0是出错 ==0是客户端关闭(这两个都要去将该cfd从树中移除 并close),>0就处理数据然后写回

2.代码实现

multi_epoll_sever.c

#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/epoll.h>
#include <fcntl.h>#define OPEN_MAX 5000
#define SERVE_PORT 9527int main()
{// 所需要的变量int lfd, cfd, efd, ret, wait_ret, i, sockfd, len;char buf[1024];// 地址结构体struct sockaddr_in serve_addr, client_addr;socklen_t client_addr_len;serve_addr.sin_family = AF_INET;                // IPV4serve_addr.sin_port = htons(SERVE_PORT);        // 绑定端口serve_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定ip(ANY系统自动分配)// 创建socketlfd = socket(AF_INET, SOCK_STREAM, 0);if (lfd < 0){perror("socket error");exit(1);}// bind绑定bind(lfd, (struct sockaddr *)&serve_addr, sizeof(serve_addr));// 设置上限listen(lfd, 128);// 创建红黑树efd = epoll_create(1); // efd就是树的根节点// 将lfd挂在树上// epoll结构体                       ep是epoll_wait所需的数组(存放满足事件的fd)struct epoll_event tep, ep[128]; //  tep是epoll_ctl的参数(传监听的事件)tep.events = EPOLLIN;tep.data.fd = lfd;ret = epoll_ctl(efd, EPOLL_CTL_ADD, lfd, &tep);if (ret < 0){perror("epoll_ctl error");exit(1);}// 循环去epoll_wait进行监听while (1){wait_ret = epoll_wait(efd, ep, 128, -1); // wait_ret就是实际满足事件的总个数// 以wait_ret为上限去遍历事件for (i = 0; i < wait_ret; i++)	{// sockfd用于接收满足事件的fdsockfd = ep[i].data.fd;// 如果等于lfd,那就说明有客户端要来连接,就去acceptif (sockfd == lfd)	{client_addr_len = sizeof(client_addr);cfd = accept(lfd, (struct sockaddr *)&client_addr, &client_addr_len);// 将cfd设置为非阻塞int flag = fcntl(cfd, F_GETFL);flag |= O_NONBLOCK;fcntl(cfd, F_SETFL, flag);// 把新的cfd加入树中tep.events = EPOLLIN | EPOLLET;tep.data.fd = cfd;ret = epoll_ctl(efd, EPOLL_CTL_ADD, cfd, &tep);if (ret < 0){perror("epoll_ctl cfd error");exit(1);}}// 如果不是lfd,那就说明有读事件发生(读数据)else{len = read(sockfd, buf, sizeof(buf));if (len == 0) // 说明对方关闭连接(从树上摘下 & close){epoll_ctl(efd, EPOLL_CTL_DEL, sockfd, NULL);close(sockfd);}else if (len == -1){perror("read error");exit(1);}else // 读写数据{for (i = 0; i < len; i++)buf[i] = toupper(buf[i]);write(sockfd, buf, len);write(STDIN_FILENO, buf, len);}}}}return 0;
}
gcc multi_epoll_sever.c -o multi_epoll_sever
//也可以使用和其他多路IO一样的封装的warp.h warp.c的版本
//就不贴warp.c和warp.c了,大家有需要可以去select和poll的博客中查看
#include"warp.h"
#define SERV_PORT 9527
#define OPEN_MAX 20
int main(int argc,char * argv[])
{int i,listenfd,connfd,efd,res,nready,sockfd;int n,num=0;char buf[4096],str[INET_ADDRSTRLEN];socklen_t clien;listenfd=Socket(AF_INET,SOCK_STREAM,0);	int opt=1;setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));struct sockaddr_in servaddr,cliaddr;struct epoll_event tep,ep[OPEN_MAX];servaddr.sin_family=AF_INET;servaddr.sin_port=htons(SERV_PORT);servaddr.sin_addr.s_addr=htonl(INADDR_ANY);Bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));Listen(listenfd,128);efd=epoll_create(OPEN_MAX);if(efd==-1)perr_exit("epoll_create error");tep.events=EPOLLIN;tep.data.fd=listenfd;res=epoll_ctl(efd,EPOLL_CTL_ADD,listenfd,&tep);if(res==-1)perr_exit("epoll_ctl error");for(;;){nready=epoll_wait(efd,ep,OPEN_MAX,-1);if(nready==-1)perr_exit("epoll_wait error");for(i=0;i<nready;i++){if(!ep[i].events&EPOLLIN)continue;if(ep[i].data.fd==listenfd){clien=sizeof(cliaddr);connfd=Accept(listenfd,(struct sockaddr *)&cliaddr,&clien);printf("received from %s at PORT %d\n",inet_ntop(AF_INET,&cliaddr.sin_addr,str,sizeof(str)),ntohs(cliaddr.sin_port));printf("cfd %d---client %d\n",connfd,++num);tep.events=EPOLLIN;tep.data.fd=connfd;res=epoll_ctl(efd,EPOLL_CTL_ADD,connfd,&tep);if(res==-1)perr_exit("epoll_ctl error");}else{sockfd=ep[i].data.fd;n=Read(sockfd,buf,4096);if(n==0){res=epoll_ctl(efd,EPOLL_CTL_DEL,sockfd,NULL);if(res==-1)perr_exit("epoll_ctl error");Close(sockfd);printf("client[%d] closed connection\n",sockfd);}else if(n<0){perror("read n<0 error:");res=epoll_ctl(efd,EPOLL_CTL_DEL,sockfd,NULL);Close(sockfd);}else{for(i=0;i<n;i++)buf[i]=toupper(buf[i]);Write(STDOUT_FILENO,buf,n);Write(sockfd,buf,n);}}}}Close(listenfd);Close(efd);return 0;
}

运行图

两个客户端访问服务器端

image-20241213104728787

相关文章:

linux网络编程 | c | epoll实现IO多路转接服务器

epoll实现IO多路转接服务器 可通过以下视频学习 06-opell函数实现的多路IO转接_哔哩哔哩_bilibili 通过响应式–多路IO转接实现 文章目录 epoll实现IO多路转接服务器1.思路&功能核心思路 2.代码实现multi_epoll_sever.c运行图 1.思路&功能 **功能&#xff1a;**客…...

Source Insight的使用经验汇总

01-Add All"和“Add Tree”有何区别&#xff1f; 在 Source Insight 中&#xff0c;“Add All”和“Add Tree”是两种向项目&#xff08;Project&#xff09;中添加文件的操作选项&#xff0c;它们的区别在于处理文件和目录的方式不同&#xff1a; 1. Add All 范围&am…...

VSCode 报错:rust-analyzer requires glibc >= 2.28 in latest build

报错信息 /home/jake/.vscode-server-insiders/extensions/matklad.rust-analyzer-0.3.953/server/rust-analyzer: /lib/x86_64-linux-gnu/libc.so.6: version GLIBC_2.29 not found (required by /home/jake/.vscode-server-insiders/extensions/matklad.rust-analyzer-0.3.9…...

Android Link to Death 使用

Java侧&#xff1a; 【android学习】使用linkToDeath对AIDL双向死亡监听_unlinktodeath-CSDN博客 Native侧&#xff1a; Service端 using namespace android; class MyService :public IBinder::DeathRecipient{void MyService::binderDied(const wp<IBinder>& wh…...

【C++游记】string的使用和模拟实现

枫の个人主页 你不能改变过去&#xff0c;但你可以改变未来 算法/C/数据结构/C Hello&#xff0c;这里是小枫。C语言与数据结构和算法初阶两个板块都更新完毕&#xff0c;我们继续来学习C的内容呀。C是接近底层有比较经典的语言&#xff0c;因此学习起来注定枯燥无味&#xf…...

DockerUI info存在未授权访问漏洞

免责声明: 本文旨在提供有关特定漏洞的深入信息,帮助用户充分了解潜在的安全风险。发布此信息的目的在于提升网络安全意识和推动技术进步,未经授权访问系统、网络或应用程序,可能会导致法律责任或严重后果。因此,作者不对读者基于本文内容所采取的任何行为承担责任。读者在…...

SQL,查询每天最接近指定时间的记录

Oracle 数据库的某表有一列是日期时间类型&#xff0c;每天对应多条数据&#xff1a; td1.1.2024 08:08:0811.1.2024 10:10:1021.1.2024 15:15:1531.1.2024 20:20:2042.1.2024 09:09:0952.1.2024 12:12:1262.1.2024 16:16:16712.12.2024 16:16:168 现在要从每天找出两条记录&…...

ElasticSearch如何做性能优化?

大家好&#xff0c;我是锋哥。今天分享关于【ElasticSearch如何做性能优化&#xff1f;】面试题。希望对大家有帮助&#xff1b; ElasticSearch如何做性能优化&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Elasticsearch 中&#xff0c;性能优化是…...

【Linux】虚拟空间布局模型地址回填数据段合并(万字详解)

Ⅰ、虚拟空间布局模型 理论模型 包括上节的动态库与静态库&#xff0c;加上本节后面两个内容其实都是对gcc的扩展与补充知识&#xff0c;也是需要了解和掌握的知识。在开讲之前&#xff0c;我们先来说一下在32位x86的Linux系统中&#xff0c;虚拟地址空间布局模型&#xff1a…...

const和修饰指针的几种用法

昨天闲着没事去面试了一个C岗位&#xff0c;问了很多基础的东西都没答上来。主要原因是这些知识在硬件资源丰富的pc端用的不多&#xff0c;二来确实很久没温习之前的C相关的知识了。在面试官问了几次类似的问题没有答好的情况下&#xff08;还喜欢问你确不确定&#xff09;&…...

mybatis事务的自动提交与手动提交

MyBatis支持自动提交和手动提交两种事务管理方式。 自动提交事务 MyBatis默认使用自动提交模式&#xff0c;即每个SQL操作都会自动提交到数据库中。这意味着在执行完一条SQL语句后&#xff0c;MyBatis会自动调用commit()方法将更改持久化到数据库。 手动提交事务 可以通过Sq…...

网络安全协议之比较(SSH、PKI、SET、SSL)

一、SSH介绍 什么是SSH&#xff1f;   传统的网络服务程序&#xff0c;如&#xff1a;ftp、pop和telnet在本质上都是不安全的&#xff0c;因为它们在网络上用明文传送口令和数据&#xff0c; 别有用心的人非常容易就可以截获这些口令和数据。而且&#xff0c;这些服务程序的…...

Vue的生命周期方法

Vue 生命周期方法详解 beforeCreate 执行时机&#xff1a;在实例初始化之后&#xff0c;数据观测&#xff08;data observer&#xff09;和事件配置&#xff08;event/watcher setup&#xff09;之前被调用。内部状态&#xff1a;此时&#xff0c;组件的选项对象&#xff08;例…...

ISP和IQ调试(一)

系列文章目录 文章目录 系列文章目录前言一、ISP&#xff08;image signal process)二、ISP位置三、IQ总结 前言 一、ISP&#xff08;image signal process) image signal process 图像处理技术 image signal processor 图像信号处理器 设备 什么是图像信号&#xff1f; 代表…...

c# TaskScheduler

这里记录下 TaskScheduler 的简单用法。 使用场景&#xff1a; 使用 Task 的时候&#xff0c;大家知道用 TaskFactory.StartNew 可以用来创建一个 Task 。这里如果创建了 3 个&#xff0c;那么这3个 Task 就各自放飞直接运行了。 class Program {private static TaskFactory…...

可视化数据

数据科学家会直观呈现数据&#xff0c;以更好地理解数据。 他们可以扫描原始数据、检查摘要度量值&#xff08;如平均值&#xff09;或绘制数据图表。 图表是一种可视化数据的强有力方式&#xff0c;数据科学家经常使用图表快速了解适度复杂的模式。 直观地表示数据 绘制图表…...

【Redis】Redis缓存击穿

1. 概述 缓存击穿&#xff1a;缓存击穿问题也叫热点key问题&#xff0c;一个高并发的key或重建缓存耗时长&#xff08;复杂&#xff09;的key失效了&#xff0c;此时大量的请求给数据库造成巨大的压力。如下图&#xff0c;线程1还在构建缓存时&#xff0c;线程2&#xff0c;3&…...

厦门凯酷全科技有限公司深耕抖音电商运营

在数字经济飞速发展的今天&#xff0c;抖音电商平台以其独特的社交属性和庞大的用户基础&#xff0c;迅速成为众多品牌和商家的新战场。在这个充满机遇与挑战的市场中&#xff0c;厦门凯酷全科技有限公司凭借其专业的服务、创新的理念和卓越的执行力&#xff0c;成为了抖音电商…...

六西格玛DMAIC在企业得项目管理中有什么作用

六西格玛&#xff08;Six Sigma&#xff09;是一种以数据为基础的管理方法&#xff0c;旨在通过减少缺陷和变异来提高过程质量和效率。DMAIC 是六西格玛中一种常用的改进方法论&#xff0c;适用于现有过程的改进。DMAIC 代表五个阶段&#xff1a;定义&#xff08;Define&#x…...

vscode借助插件调试OpenFoam的正确的.vscode配置文件

正确的备份文件位置&#xff1a; /home/jie/桌面/理解openfoam/正确的调试爆轰单进程案例/mydebugblastFoam 调试爆轰案例流体 并且工作区和用户区都是openfoam-7版本 问题&#xff1a;F5以debug模式启动后不停在断点 解决方法&#xff1a; 这里备份一下.vsode正确的配置&…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说&#xff0c;在叠衣服的过程中&#xff0c;我会带着团队对比各种模型、方法、策略&#xff0c;毕竟针对各个场景始终寻找更优的解决方案&#xff0c;是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

Modbus RTU与Modbus TCP详解指南

目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...