当前位置: 首页 > 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>再次注册相同的回调将用提供…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

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…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...

SpringAI实战:ChatModel智能对话全解

一、引言&#xff1a;Spring AI 与 Chat Model 的核心价值 &#x1f680; 在 Java 生态中集成大模型能力&#xff0c;Spring AI 提供了高效的解决方案 &#x1f916;。其中 Chat Model 作为核心交互组件&#xff0c;通过标准化接口简化了与大语言模型&#xff08;LLM&#xff0…...