epoll多路复用_并发服务器

应用程序:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <fcntl.h>
#include <stdlib.h>#define ERR_MSG(msg)                   \do                                 \{                                  \printf("line:%d\n", __LINE__); \perror(msg);                   \} while (0)#define PORT 6666            //端口号
#define IP "192.168.250.100" // IP地址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 sfd=%d __%d__\n", sfd, __LINE__);//设置端口快速被复用int reuse = 1;if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0){ERR_MSG("setsockopt");return -1;}//填充服务器自身的地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(PORT);sin.sin_addr.s_addr = inet_addr(IP);//存储客户端信息结构体int s_res = 0;struct sockaddr_in cin;socklen_t len = sizeof(cin);struct sockaddr_in savecin[1024];//将IP地址和端口号绑定到指定的套接字文件描述符上if (bind(sfd, (struct sockaddr *)&sin, sizeof(sin)) < 0){ERR_MSG("bind");return -1;}printf("bind success __%d__\n", __LINE__);//将套接字设置为被动监听状态if (listen(sfd, 128) < 0){ERR_MSG("listen");return -1;}printf("listen success __%d__\n", __LINE__);char buf[128] = "";ssize_t res = 0;// epollint fd, newfd, epfd;struct epoll_event event;struct epoll_event events[10]; //存放就绪事件描述符的数组//创建epoll句柄epfd = epoll_create(1);if (epfd < 0){printf("epoll_create filed\n");exit(-1);}event.events = EPOLLIN;event.data.fd = sfd;if (epoll_ctl(epfd, EPOLL_CTL_ADD, sfd, &event) < 0){printf("epoll_ctl add filed\n");}//监听事件是否发生while (1){//等待事件发生int ret = epoll_wait(epfd, events, 10, -1);if (ret < 0){printf("epoll_wait filed\n");exit(-1);}int i;//循环遍历数组,做事件的处理for (i = 0; i < ret; i++){//监听到新连接if (events[i].data.fd == sfd){newfd = accept(sfd, (struct sockaddr *)&cin, &len);if (newfd < 0){perror("accept");return -1;}printf("[%s:%d] 客户端连接成功 newfd=%d __%d__\n",inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, __LINE__);savecin[newfd] = cin;//新客户端套接字加入epollevent.events = EPOLLIN;event.data.fd = newfd;if (epoll_ctl(epfd, EPOLL_CTL_ADD, newfd, &event) < 0){printf("epoll_ctl add filed\n");}}else if (events[i].data.fd == 0) //键盘输入事件{printf("触发键盘输入事件 __%d__\n", __LINE__);int sndfd = -1;res = scanf("%d %s", &sndfd, buf);while (getchar() != 10);if (res != 2){printf("请输入正确数据格式:fd string\n");continue;}}else{//客户端交互事件printf("触发客户端交互事件__%d__\n", __LINE__);bzero(buf, sizeof(buf));//接收数据res = recv(events[i].data.fd, buf, sizeof(buf), 0);if (res < 0){ERR_MSG("recv");return -1;}else if (0 == res){printf("[%s:%d] 客户端下线 newfd=%d __%d__\n",inet_ntoa(savecin[i].sin_addr), ntohs(savecin[i].sin_port), i, __LINE__);close(i); //未接收到数据,关闭文件描述符continue; //进入下一次循环}//发送数据strcat(buf, "*_*");if (send(events[i].data.fd, buf, sizeof(buf), 0) < 0){ERR_MSG("send");return -1;}printf("发送成功\n");}}}if (close(sfd) < 0){ERR_MSG("close");return -1;}return 0;
}

驱动程序:

#include <linux/init.h>
#include <linux/module.h>
#include<linux/fs.h>
#include<linux/io.h>
#include<linux/device.h>
#include<linux/uaccess.h>
#include<linux/poll.h>
struct class *cls;
struct device *dev;
unsigned int major;//定义一个变量保存主设备号
char kbuf[128]={0};
//定义等待队列头
wait_queue_head_t wq_head;
int condition=0;//数据是否准备好的标志变量
//封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
ssize_t mycdev_read(struct file *file, char  *ubuf, size_t size, loff_t *lof)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);if(size>sizeof(kbuf))//用户的需求内核满足不了{size=sizeof(kbuf);}long ret;ret=copy_to_user(ubuf,kbuf,size);if(ret){printk("copy_to_user filed\n");return -EIO;}condition=0;//表示下一次数据没有准备好return 0;
}
ssize_t mycdev_write(struct file *file, const char  *ubuf, size_t size, loff_t *lof)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);if(size>sizeof(kbuf))//用户的需求内核满足不了{size=sizeof(kbuf);}long ret;ret=copy_from_user(kbuf,ubuf,size);//表示模拟硬件数据就绪if(ret){printk("copy_from_user filed\n");return -EIO;}condition=1;wake_up_interruptible(&wq_head);//唤醒休眠的进程return 0;
}
//封装poll方法
__poll_t mycdev_poll(struct file *file, struct poll_table_struct *wait)
{__poll_t mask=0;//1.向上提交等待队列头poll_wait(file,&wq_head,wait);//2.根据事件是否发生给一个合适的返回值if(condition){mask=POLLIN;}return mask;
}
int mycdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
//定义一个操作方法结构体变量并且初始化
struct file_operations fops={.open=mycdev_open,.release=mycdev_close,.read=mycdev_read,.poll=mycdev_poll,.write=mycdev_write,
};
static int __init mycdev_init(void)
{//初始化等待队列头init_waitqueue_head(&wq_head);//注册字符设备驱动major=register_chrdev(0,"mychrdev",&fops);if(major<0){printk("注册字符设备驱动失败\n");return major;}printk("注册字符设备驱动成功major=%d\n",major);// 向上提交目录cls = class_create(THIS_MODULE, "myled");if (IS_ERR(cls)){printk("向上提交目录失败\n");return -PTR_ERR(cls);}printk("向上提交目录信息成功\n");// 向上提交设备节点信息dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "mycdev");if (IS_ERR(dev)){printk("向上提交设备节点信息失败\n");return -PTR_ERR(dev);}printk("向上提交设备节点成功\n");return 0;
}
static void __exit mycdev_exit(void)
{// 销毁节点信息device_destroy(cls, MKDEV(major, 0));// 销毁目录信息class_destroy(cls);//注销字符设备驱动unregister_chrdev(major,"mychrdev");}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

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

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

相关文章

【数据结构】_5.栈

目录 1. 概念 2. 栈的使用 2.1 方法 2.2 示例 3. 栈的模拟实现 4. 栈的应用场景 4.1 题目1&#xff1a;不可能的出栈序列 4.2 题目2&#xff1a;逆序打印单链表 4.3 题目3&#xff1a;逆波兰表达式求值 4.4 题目4&#xff1a;括号匹配 4.5 题目5&#xff1a;栈的压入…

mysql月统计数据,没有的填充为0

要按时间戳字段按月份分组查询记录表&#xff0c;可以使用DATE_FORMAT函数将时间戳字段格式化为年月格式&#xff0c;然后将结果按照该字段进行分组。 SELECT a.month month,ifnull(b.count, 0) count FROM (SELECT 1 month UNION ALL SELECT 2 month UNION ALL SELECT 3 mont…

Day04-作业(MavenSpringBootWeb入门)

作业1&#xff1a;创建maven工程并配置相关依赖&#xff0c;完成如下需求 需求&#xff1a; 创建三个maven工程&#xff0c;projectA/projectB/projectC&#xff0c;在同一个idea窗口打开 三个maven工程设置依赖&#xff0c;关系入下图所示 作业2&#xff1a;基于SpringBoot…

走进人工智能|自动驾驶 开启智能出行新时代

前言 自动驾驶&#xff0c;也被称为无人驾驶或自动驾驶汽车&#xff0c;是指能够在没有人类干预的情况下自主地感知环境、决策和控制车辆行驶的技术和系统。 文章目录 前言主题发展趋势自动驾驶等级L0级自动驾驶L1级别自动驾驶L2级别自动驾驶L3级别自动驾驶L4级别自动驾驶L5级…

MySQL 在CentOS下安装

yum安装 1、yum源安装 yum install mariadb-server2、启动MySQL服务 systemctl start mariadb3、查看运行状态 systemctl status mariadb4、设置初始密码 mysql -u rootuse mysql;update user set passwordpassword("root")where userroot;flush privileges;e…

【LeetCode】5. 最长回文串

题目链接 文章目录 1. 思路讲解2. 代码实现 1. 思路讲解 与求回文子串思路差别不大 在做这道题目之前&#xff0c;可以先做一下另一道回文子串的题目&#xff0c;如果会了那道求回文子串的题目&#xff0c;这道题基本上也就会了。 回文子串的题解在这里 它也就是求出每一个回…

音乐节《迷笛音乐节》游玩感

上周&#xff0c;去了烟台&#xff0c;参加音乐节&#xff0c;以前从未参加过&#xff0c;所以趁着本周六周日双休的时候&#xff0c;去游玩了一次。&#xff08;1&#xff09;一种新奇体验 对于自己来说&#xff0c;参加音乐节还是一种新奇的体验的&#xff0c;也是疫情放开了…

苍穹外卖day09——历史订单模块(用户端)+订单管理模块(管理端)

查询历史订单——需求分析与设计 产品原型 业务规则 分页查询历史订单 可以根据订单状态查询 展示订单数据时&#xff0c;需要展示的数据包括&#xff1a;下单时间、订单状态、订单金额、订单明细&#xff08;商品名称、图片&#xff09; 接口设计 查询历史订单——代码开…

python小案例

以下是采集店铺链接并去重的代码示例&#xff1a; import requestsfrom bs4 import BeautifulSoupdef get_shop_links(item_url): # 访问宝贝详情页面 response requests.get(item_url) soup BeautifulSoup(response.text, html.parser) # 获取必逛好店的店铺…

ChatGPT在法律行业的市场潜力

​ChatGPT现在已经成为我们的文字生成辅助工具、搜索引擎助手&#xff0c;许多体验过它的朋友会发现对它越来越依赖&#xff0c;并将其逐渐融入到自己的日常工作、生活。但有一点值得注意&#xff1a;这种人工智能除了技术可行、经济价值可行还要与相关规范即人类普遍的价值观念…

数电与Verilog基础知识之always关键词及其相关

Verilog语言中三种固定的always关键词&#xff0c;它们分别是always_ff、always_latch和always_comb。它们都是用来描述电路元件的行为的&#xff0c;但是它们有不同的用途和限制。它们的工作原理如下&#xff1a; always_ff是用来描述触发器的行为的&#xff0c;它只能包含时…

所有集群启动的命令

所有集群启动的命令 查询所有节点启动Hadoop集群(Yarn模式)关闭Hadoop集群Spark&#xff08;local模式&#xff09;启动Spark集群standalone模式(不用了)关闭standalone模式HA下的standalone模式关闭HA-standalone模式Yarn模式&#xff08;重点&#xff09; 关闭Spark集群启动f…

python_day16_设计模式

“”“单例模式”“” “”“工厂模式”“” class Person:passclass Worker(Person):passclass Student(Person):passclass Teacher(Person):passclass Factory:def get_person(self, p_type):if p_type w:return Worker()elif p_type s:return Student()else:return Te…

代码随想录算法训练营第四十六天| 139.单词拆分 背包问题总结

代码随想录算法训练营第四十六天| 139.单词拆分 背包问题总结 一、力扣139.单词拆分 题目链接&#xff1a; 思路&#xff1a;确定dp数组&#xff0c;dp[i]为true表示从0到i切分的字串都在字典中出现过。 确定递推公式&#xff0c;dp[i] 为true要求 s[j, i] 在字典中出现&…

【雕爷学编程】MicroPython动手做(25)——语音合成与语音识别2

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

排序(合集)

题目描述 将读入的 N 个数从小到大排序后输出。 输入格式 第一行为一个正整数 N。 第二行包含 N 个空格隔开的正整数 ai​&#xff0c;为你需要进行排序的数。 输出格式 将给定的 N 个数从小到大输出&#xff0c;数之间空格隔开&#xff0c;行末换行且无空格。 输入输出…

偶数科技与白鲸开源完成兼容性认证

近日&#xff0c;偶数科技自主研发的云原生分布式数据库 OushuDB v5.0 完成了与白鲸开源集成调度工具 WhaleStudio v2.0 的兼容性相互认证测试。 测试结果显示&#xff0c;双方产品相互良好兼容&#xff0c;稳定运行、安全&#xff0c;同时可以满足性能需求&#xff0c;为企业级…

Android 自定义按钮(可滑动、点击)

按钮图片素材 https://download.csdn.net/download/Lan_Se_Tian_Ma/88151085 px 和 dp 转换工具类&#xff08;Java&#xff09; // px 和 dp 转换工具类 public class DensityUtil {/*** 根据手机的分辨率从 dip 的单位 转成为 px(像素)*/public static int dip2px(Conte…

浅谈webpack

文章目录 Webpackwebpack的工作原理webpack的构建流程Webpack的基本功能有哪些Webpack常用配置 Webpack Webpack是一个现代的JavaScript应用程序静态模块打包工具。它是一个用于构建和打包前端资源的工具&#xff0c;可以将多个模块和资源&#xff08;如JavaScript、CSS、图片…

【C++】基于多设计模式下的同步异步日志系统

✍作者&#xff1a;阿润021 &#x1f4d6;专栏&#xff1a;C 文章目录 一、项目介绍二、项目实现准备工作1.日志系统技术实现策略2.相关技术知识补充2.1 不定参函数设计2.2 设计模式 三、日志项目框架设计1.模块划分2.各模块关系图 四、详细代码实现1.实用工具类设计2.日志等级…