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

2023.07.29 驱动开发DAY6

通过epoll实现一个并发服务器

服务器

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>#define ERR_MSG(msg)               \
do {                               \printf("LINE: %d\n", __LINE__);\perror(msg);                   \
} while(0)#define PORT 6666
#define IP "127.0.0.1"int main(int argc,const char * argv[])
{//创建流式套接字int sfd = socket(AF_INET, SOCK_STREAM, 0);if(sfd < 0){ERR_MSG("socket");return -1;}printf("socket create success\n");//允许端口快速复用int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0){ERR_MSG("setsockopt");return -1;}printf("setsockopt success\n");//填充地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(PORT);sin.sin_addr.s_addr = inet_addr(IP);//将IP地址和端口号绑定到指定的套接字文件描述符上if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0){ERR_MSG("bind");return -1;}printf("bind success\n");//将通讯套接字设置为被动监听状态if(listen(sfd, 128) < 0){ERR_MSG("listen");return -1;}printf("listen success\n");// 创建epoll句柄int epfd = epoll_create(1);if(epfd < 0){printf("epoll_create filed\n");return -1;}// 添加准备就绪事件进入epoll;struct epoll_event event;struct epoll_event events[10]; //存放就绪事件描述符的数组event.events = EPOLLIN; // 读事件event.data.fd = sfd;if(epoll_ctl(epfd, EPOLL_CTL_ADD, sfd, &event) < 0){printf("epoll_ctl add filed\n");}//监听事件是否发生struct sockaddr_in cin;        //存储客户端信息socklen_t len = sizeof(cin);struct sockaddr_in savecin[1024];int ret, res;char buf[128] = {};while(1){//如果成功,ret接收返回的事件个数,把就绪的事件放在events数组中ret = epoll_wait(epfd, events, 10, -1);if(ret < 0){printf("epoll_wait filed\n");return -1;}//循环遍历数组,做事件处理for(int i=0; i<ret; i++){if(events[i].events & EPOLLIN){if(events[i].data.fd == sfd){//触发客户端连接事件int newfd = accept(sfd, (struct sockaddr*)&cin, &len);if(newfd < 0){ERR_MSG("accpet");return -1;}printf("[%s:%d] 客户端连接成功 newfd=%d\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd);savecin[newfd] = cin;//添加新连接客户端进入epoll;event.events = EPOLLIN; // 读事件event.data.fd = newfd;if(epoll_ctl(epfd, EPOLL_CTL_ADD, newfd, &event) < 0){printf("epoll_ctl add filed\n");return -1;}}else{//触发客户端交互事件                   //接收数据int cfd = events[i].data.fd;bzero(buf, sizeof(buf));res = recv(cfd, buf, sizeof(buf), 0);if(res < 0){ERR_MSG("recv");return -1;}else if(res == 0){printf("[%s:%d] 客户端下线 cfd=%d\n", inet_ntoa(savecin[cfd].sin_addr), ntohs(savecin[cfd].sin_port), cfd);close(cfd); // 关闭文件描述符//添加断开连接的客户端从epoll中删除;if(epoll_ctl(epfd, EPOLL_CTL_DEL, cfd, NULL) < 0){printf("epoll_ctl del filed\n");return -1;}continue;}printf("[%s:%d] cfd=%d: %s\n", inet_ntoa(savecin[cfd].sin_addr), ntohs(savecin[cfd].sin_port), cfd, buf);// 发送数据strcat(buf, "*_*");if(send(cfd, buf, sizeof(buf), 0) < 0){ERR_MSG("send");return -1;}}}}}return 0;
}

客户端

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>#define ERR_MSG(msg)               \
do {                               \printf("LINE: %d\n", __LINE__);\perror(msg);                   \
} while(0)#define PORT 6666
#define IP "127.0.0.1"int main(int argc,const char * argv[])
{//创建流式套接字int cfd = socket(AF_INET, SOCK_STREAM, 0);if(cfd < 0){ERR_MSG("socket");return -1;}printf("socket create success\n");//填充地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(PORT);sin.sin_addr.s_addr = inet_addr(IP);//连接到服务器if(connect(cfd, (struct sockaddr*)&sin, sizeof(sin)) < 0){ERR_MSG("connect");return -1;}printf("connect server success\n");char buf[128] = "";ssize_t res = 0;while(1){//发送数据bzero(buf, sizeof(buf));printf("请输入>>> ");fgets(buf, sizeof(buf), stdin);buf[strlen(buf)-1] = 0;if(send(cfd, buf, sizeof(buf), 0) < 0){ERR_MSG("send");return -1;}printf("发送成功\n");//接收数据bzero(buf, sizeof(buf));res = recv(cfd, buf, sizeof(buf), 0);if(res < 0){ERR_MSG("recv");return -1;}else if(0 == res){printf("[%s:%d] 服务器下线\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));break;}printf("[%s:%d]: %s\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), buf); }close(cfd);return 0;
}

运行结果

 

相关文章:

2023.07.29 驱动开发DAY6

通过epoll实现一个并发服务器 服务器 #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/epoll.h…...

网工必须掌握的5种组网技术,你会了吗?

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 一、VLAN技术 1、VLAN是什么&#xff1f; 2、VLAN的作用 ①提高网络安全性 ②提高了网络的灵活性性 ③增强了网络的健壮性 二、D…...

webpack中文文档

基本安装 首先我们创建一个目录&#xff0c;初始化 npm&#xff0c;然后 在本地安装 webpack&#xff0c;接着安装 webpack-cli&#xff08;此工具用于在命令行中运行 webpack&#xff09;&#xff1a; mkdir webpack-demo cd webpack-demo npm init -y npm install webpack …...

【Linux指令篇】--- Linux常用指令汇总(克服指令繁杂问题)

文章目录 前言&#x1f31f;一、Linux基本指令&#x1f31f;二、ls指令&#x1f30f;2.1.语法&#xff1a;&#x1f30f;2.2.功能&#xff1a;&#x1f30f;2.3.常用选项&#xff1a; &#x1f31f;三、pwd指令&#x1f30f;3.1.语法&#xff1a;&#x1f30f;3.2.功能&#xf…...

硬盘的分类

目前常见的硬盘种类主要有以下2种&#xff1a; 机械硬盘&#xff08;HDD&#xff09; 机械硬盘&#xff08;HDD&#xff09;是一种利用旋转磁盘和读写头来存储和访问数据的存储设备。它由磁盘、读写头、电机和控制电路等组成&#xff0c;磁盘通常是一种铝合金或玻璃材质的圆盘&…...

el-upload批量手动上传,并用form表单校验上传文件

手动上传设置:auto-upload"false" <el-formref"formData"class"formWidth":model"formData"label-width"120px":rules"rules"><el-form-itemlabel"数据"class"uploadClass"required…...

牛客网Verilog刷题——VL52

牛客网Verilog刷题——VL52 题目答案 题目 请编写一个十进制计数器模块&#xff0c;当mode信号为1&#xff0c;计数器输出信号递增&#xff0c;当mode信号为0&#xff0c;计数器输出信号递减。每次到达0&#xff0c;给出指示信号zero。模块的接口信号图如下&#xff1a; 模块的…...

4-7月预测价差方向准确率统计

月度 预测价差方向准确率 4月 33.6% 5月 28.4% 6月 25.7% 7月 34.2% 4-7月合计 30.6% 准确率计算公式&#xff1a; 其中&#xff0c; D&#xff1a;价差方向预测值&#xff08;1:实时>日前&#xff0c;0:实时日前&#xff0c;-1&#xff1a;实时<日前&#x…...

《Vue3+Typescript》一个简单的日历组件实现

这是一个没有套路的前端博主&#xff0c;热衷各种前端向的骚操作&#xff0c;经常想到哪就写到哪&#xff0c;如果有感兴趣的技术和前端效果可以留言&#xff5e;博主看到后会去代替大家踩坑的&#xff5e; 主页: oliver尹的主页 格言: 跌倒了爬起来就好&#xff5e; 目录 一、…...

第一章 修学旅行

前言 翻了翻文章回收站&#xff0c;好怀念靖和阳的故事啊&#xff08;航和颜&#xff1a;还有我们别忘啦&#xff09; 不知道还有没有人记得以前的故事呢…… 那么&#xff0c;我就开始写啦。这是关于密码学的一篇文章&#xff0c;一共2696字&#xff1a;D&#xff08;累死我…...

如果你也能认识并使用这个低代码平台,那真的是泰酷辣——iVX低代码平台

低代码技术起源是比较悠久的了&#xff0c;尤其是在近些年&#xff0c;随着技术的演进&#xff0c;低代码平台逐渐成为热门趋势。这些平台通过简化应用程序开发流程&#xff0c;减少手动编码&#xff0c;使非专业开发人员也能快速构建复杂应用。为我们的敏捷开发和高效生产贡献…...

uC-OS2 V2.93 STM32L476 移植:系统移植篇

前言 上一篇已经 通过 STM32CubeMX 搭建了 NUCLEO-L476RG STM32L476RG 的 裸机工程&#xff0c;并且下载了 uC-OS2 V2.93 的源码&#xff0c;接下来&#xff0c;开始系统移植 开发环境 win10 64位 Keil uVision5&#xff0c;MDK V5.36 uC-OS2 V2.93 开发板&#xff1a;NUC…...

gitee修改代码提交操作步骤说明

一&#xff0c;简介 本文主要介绍如何从gitee仓库下载文件&#xff0c;本地修改&#xff0c;本地提交&#xff0c;然后再push到远程服务器的操作步骤。供参考&#xff0c;欢迎一起讨论交流~ 二&#xff0c;操作步骤 总的操作步骤分为以下几步 1&#xff0c;远程服务器下载文…...

物联网|可变参数的使用技巧|不一样的点灯实验|访问外设的寄存器|操作寄存器实现点灯|硬件编程的基本流程-学习笔记(11)

文章目录 可变参数的使用技巧第三阶段-初级实验Lesson5:不一样的点灯实验---学习I/O的输出 ☆点灯的电路图分析1 一起看看点灯的电路图Tip1:另一种点灯的电路Tip1:如何访问外设的寄存器2 STM32F407中操作GPIO的方法 通过直接操作寄存器实现点灯实验Tip1:硬件编程的基本流程 2代…...

30. 利用linprog 解决 生产决策问题(matlab程序)

1.简述 线线规划的几个基本性质&#xff1a;【文献[1]第46页】 (1)线性规划问题的可行域如果非空&#xff0c;则是一个凸集-凸多面体&#xff1b; (2)如果线性规划问题有最优解&#xff0c;那么最优解可在可行域的顶点中确定&#xff1b; (3)如果可行域有界&#xff0c;且可行域…...

一百三十九、Kettle——Linux安装Kettle8.2

一、目的 为了方便海豚调度kettle任务&#xff0c;在Linux上安装kettle 二、kettle版本与前提 版本&#xff1a;kettle8.2 pdi-ce-8.2.0.0-342 前提&#xff1a;Linux已经安装好jdk 三、安装步骤 &#xff08;一&#xff09;打开安装包所在地 [roothurys22 ~]# cd …...

react路由在layout中的监听

业务中需要在layout里来监听路由的变化&#xff0c;但是layout并不是一个路由组件&#xff0c;所以layout组件内的props并没有location,history等属性&#xff0c;&#xff08;路由组件&#xff1a;由Route组件处理的才是路由组件&#xff09;所以我们需要将layout组件转变成路…...

Java反射(三)

目录 1.反射与代理设计模式 2.反射与Annotation 3.自定义Annotation 4.Annotation整合工厂设计模式和代理设计模式 1.反射与代理设计模式 代理模式是指通过业务真实类实现业务接口&#xff0c;再通过设置代理类创建业务真实类子类从而间接访问业务真实类。但是这存在一个弊…...

ansible-playbook roles编写lnmp剧本

目录 集中式编写lnmp剧本 执行 分布式编写lnmp剧本 一定要设置ssh免交互 nginx mysql php 执行 集中式编写lnmp剧本 vim /etc/ansible/lnmp.yml - name: lnmp playhosts: dbserversremote_user: roottasks:- name: perpare condifurecopy: src/etc/yum.repos.d/nginx.r…...

相机可用性变化监听AvailabilityCallback流程分析

相机可用性变化监听及流程分析 一、接口说明 ​ 相机可用性变化监听可以通过CameraManager中的接口registerAvailabilityCallback()来设置回调&#xff0c;接口如下&#xff1a; /** *注册一个回调以获得有关相机设备可用性的通知。 * *<p>再次注册相同的回调将用提供…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

沙箱虚拟化技术虚拟机容器之间的关系详解

问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西&#xff0c;但是如果把三者放在一起&#xff0c;它们之间到底什么关系&#xff1f;又有什么联系呢&#xff1f;我不是很明白&#xff01;&#xff01;&#xff01; 就比如说&#xff1a; 沙箱&#…...

Spring Boot + MyBatis 集成支付宝支付流程

Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例&#xff08;电脑网站支付&#xff09; 1. 添加依赖 <!…...

规则与人性的天平——由高考迟到事件引发的思考

当那位身着校服的考生在考场关闭1分钟后狂奔而至&#xff0c;他涨红的脸上写满绝望。铁门内秒针划过的弧度&#xff0c;成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定"&#xff0c;构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...