仿muduo库实现并发服务器

  • 1.Poller模块
    • 成员变量
    • 创建epoll模型
    • 对于一个描述符添加或修改事件监控
    • 对于一个描述符移除事件监控
    • 启动epoll事件监控,获取所有活跃连接

1.Poller模块

Poller模块主要是对任意的描述符进行IO事件监控。
它是对epoll的封装,可以让对描述符进行事件监控的操作更加简单。

它与Channel的关系:
一旦有活跃事件了,只有获取到这个连接的Channel对象,才能知道该连接要监控的事件是什么,知道事件就绪如何去处理。

主要的流程:
1.对描述符进行监控,但是要注意监控的对象是channel对象,因为只有channel对象才能找到该描述符要监控什么事件。
2.当描述符就绪时,通过描述符映射找到channel对象(通过hash找到channel对象),因为只有找到channel对象,才能知道就绪的事件如何处理。所以当描述符就绪时,就返回对应的channel对象。

成员变量

private:int _epfd;                                   // 用来标识epoll模型struct epoll_event _evs[DEFALUTMAX];         // 用来保存所有就绪的事件信息,信息1:就绪的描述符fd是谁。信息2:就绪的事件是什么std::unordered_map<int, Channel *> _channel; // 用来保存所有要监控的描述符信    

1.poller是封装epoll对描述符进行操作,所以一定要有一个epoll句柄。
2.当事件就绪时,就绪的事件信息就会保存在struct epoll_event 结构体数据中,保存的信息有就绪的描述符fd,就绪的事件。
3.poller是用来监控管理所有要监控的描述符,所以需要一个容器保存所有监控的描述符。
而poller监控的对象是channel,所以使用hash通过描述符映射对应的channel。这样就可以保存管理所有监控的描述符对象。

创建epoll模型

创建epoll模型,使用epoll_create()接口,返回值就是对应的epoll句柄。

// 创建epoll模型Poller(){_epfd = epoll_create(DEFALUTMAX); // 创建一个epoll模型if (_epfd < 0){ERRLog("epoll create failed");abort(); // 这个出错了就直接退出}}

对于一个描述符添加或修改事件监控

对描述符进行添加或修改事件监控,需要使用的接口是epoll_ctl(),不过这里对epoll_ctl()的操作先封装起来,外部直接调用这个封装好的epoll_ctl接口

要想对一个描述符添加事件监控,首先需要知道该描述符的fd,要监控的事件是什么,要进行操作是什么等细节。而描述符的fd,以及要监控的事件是什么都在channel对象里,所以传入一个channel对象,以及所需要进行操作即可。

不过在对一个连接真正添加和修改或者移除事件之前,还是需要判断一个该连接是否已经被添加到内核里面去了,如果已经被添加进去了,那么要进行的操作就是更新修改了,就不是添加了。所以我们还需要封装一个判定是否已经设置了监控的接口。
如何判断呢?就判断管理的哈希表中是否存在对于的channel对象即可。

 // 直接对epoll_ctl进行操作void Update(Channel *channel, int op){int fd = channel->Fd();//获取该channnel对应的描述符fdstruct epoll_event ev;ev.data.fd = fd;//设置要关系的fdev.events = channel->Events();//设置要关系的事件int ret = epoll_ctl(_epfd, op, fd, &ev);//对于一个描述符进行添加或修改事件监控if (ret < 0){ERRLog("epoll_ctl failed");}}// 判断一个连接channel是否设置了事件监控,就看_channel中是否有该连接bool HasChannel(Channel *channel){auto it = _channel.find(channel->Fd());if (it == _channel.end())return false; // 没找到return true;}

所以在内部封装了两个接口,对外真正提供的接口则是:

// 对于一个描述符添加或修改事件监控void UpdateEvent(Channel *channel){// 首先判断该连接是否已经被设置监控了,如果没有则添加监控,如果有则进行修改if (HasChannel(channel) == false){_channel.insert(std::make_pair(channel->Fd(), channel));//_channel[channel->Fd()]=channel;Update(channel, EPOLL_CTL_ADD);//}else{Update(channel, EPOLL_CTL_MOD);}}

对于一个描述符移除事件监控

对于描述符进行移除事件监控,主要有两个步骤:
1.从管理的hash表里移除(erase)
2.从红黑色树上移除(epoll_ctl,DEL)

 // 对于一个描述符移除事件监控void RemoveEvent(Channel *channel){auto it = _channel.find(channel->Fd());//在哈希表中找到该channel对象if (it != _channel.end()){_channel.erase(it);//从哈希表中删除该channnel对象}Update(channel, EPOLL_CTL_DEL);//从内核中删除该监控}

启动epoll事件监控,获取所有活跃连接

启动事件监控,就是epoll进行等待事件就绪。
当有事件就绪时,epoll就不再等待,就会返回,并将就绪的信息带回来。
就绪的信息有哪个文件描述符的什么事件就绪了,光有这些信息是没有用的,因为对于描述符的channel对象不知道什么事件就绪啊,只有channel对象才能知道就绪后该怎么操作。所以需要将该描述符的什么事件就绪信息设置进对应的channel对象中(通过描述符在哈希表中映射找到channel对象),这样channel对象才能知道它就绪了什么事件,并且可以进行对应的处理,
所以我们可以通过一个vector数组,将所有就绪的channel对象全部存储起来。
供外层eventloop取出,全部依次执行对应的操作。
操作:
1.epoll进行等待监控
2.epoll返回,将就绪的信息设置到对应的channel对象中
3.保存所有就绪的channel对象。
通过一个输出型参数将数据带出来。

 // 开始监控,并返回所有活跃连接void Poll(std::vector<Channel *> *active){int nfds = epoll_wait(_epfd, _evs, DEFALUTMAX, -1); // 默认为阻塞等待if (nfds < 0){if (errno == EINTR){return;}ERRLog("epoll wait failed:%s\n", strerror(errno));abort();}for (int i = 0; i < nfds; i++)//有事件就绪了{int fd = _evs[i].data.fd;                    // 活跃的fd是哪个、assert(_channel.find(fd) != _channel.end()); // 不能在管理的channel里找不到// 找到之后就将就绪的事件信息设置到对应的channel里_channel[fd]->SetRevents(_evs[i].events);active->push_back(_channel[fd]); // 将活跃的连接插入进去,保存起来}}

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

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

相关文章

小程序学习笔记:使用 MobX 实现全局数据共享,实例创建、计算属性与 Actions 方法

在小程序开发过程中&#xff0c;组件间的数据共享是一个常见且关键的问题。今天&#xff0c;我们就来深入探讨一下如何在小程序中实现全局数据共享&#xff0c;借助 MobX 相关的包&#xff0c;让数据管理变得更加高效便捷。 什么是全局数据共享 全局数据共享&#xff0c;也被…

观测云 × AWS SSO:权限治理可观测实践

AWS IAM Identity Center 介绍 AWS IAM Identity Center&#xff08;原 AWS Single Sign-On&#xff09;是 AWS 提供的一项云原生身份与访问管理&#xff08;IAM&#xff09;服务&#xff0c;旨在集中简化多 AWS 账户、多业务应用的安全访问控制。 观测云 观测云是一款专为 …

springboot整合配置swagger3

一. swagger3介绍 Swagger 3 是基于 OpenAPI 规范 3.0 的 API 文档工具&#xff0c;用于设计、构建和消费 RESTful API。它通过标准化描述 API 的接口、参数、响应等元数据&#xff0c;实现以下核心功能&#xff1a; 自动生成交互式文档API 测试与调试代码生成&#xff08;客…

RabbitMQ 4.1.1初体验

为什么选择 RabbitMQ&#xff1f;* RabbitMQ 是一款可靠且成熟的消息代理和流处理中间件&#xff0c;可轻松部署在云端、本地数据中心或您的开发机上&#xff0c;目前已被全球数百万用户使用。 优势在哪里 互操作性 RabbitMQ 支持多种开放标准协议&#xff0c;包括 AMQP 1.0 和…

【精华】QPS限流等场景,Redis其他数据结构优劣势对比

下面是一个详细的 Redis 数据结构对比表&#xff0c;比较它们在实现 QPS 限流 / 滑动窗口统计 / 查定比监控等场景中的适用性&#xff1a; ✅ Redis 数据结构对比表&#xff08;用于接口限流 / QPS 监控&#xff09; 维度String INCR 固定窗口List 滑动窗口Hash 计数器ZSet 滑…

顶层设计:支持单元化、灰度化的应用架构

一、顶层目标 业务连续性&#xff1a;任何单元故障不影响整体弹性伸缩&#xff1a;根据业务流量横向扩展灵活灰度&#xff1a;任何发布都可逐步平滑上线成本可控&#xff1a;单元化带来的资源冗余最小 二、核心理念 设计目标核心理念单元化垂直拆分&#xff0c;分而治之&…

MacOS Safari 如何打开F12 开发者工具 Developer Tools

背景 If you’re a web develper, the Safari Develop menu provides tools you can use to make sure your website works well with all standards-based web browsers. 解决 If you don’t see the Develop menu in menu bar, Choose Safari > settingsClick Advanced…

2025—暑期训练一

A 本题描述了一个最优路径规划问题的解法&#xff0c;核心思路是利用数轴上区间覆盖的特性&#xff0c;将问题简化为两个端点的访问问题。以下是关键点的详细解析&#xff1a; 核心观察 区间覆盖特性 给定的位置数组 x1, x2, ..., xn 是严格递增的&#xff08;即 x1 < x2 …

ubuntu 18.04配置镜像源

配置镜像源的主要作用是优化软件下载速度、提升系统更新稳定性&#xff0c;并确保软件包获取的可靠性 我这里配置阿里云镜像源 镜像的具体内容参考此文: 文章链接 以防万一,先备份一下 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak然后开始修改 sudo nano /etc…

RecyclerView中跳转到最后一条item并确保它在可视区域内显示

在RecyclerView中跳转并显示最后一条Item 要在RecyclerView中跳转到最后一条item并确保它在可视区域内显示&#xff0c;可以使用以下几种方法&#xff1a; 1. 使用scrollToPosition()方法&#xff08;基本方法&#xff09; recyclerView.scrollToPosition(adapter.getItemCo…

ubuntu22 桌面版开启root登陆

一、先创建root sudo passwd root 二、注释代码 vim /etc/pam.d/gdm-password vim/etc/pam.d/gdm-autologin 都注释 auth required pam_succeed_if.so user ! root quiet_success 三、修改profile文件 vim /root/.profile 注释掉 mesg n 2&#xff1e; /dev/null || true 插入新…

docker学习二天之镜像操作与容器操作

镜像的一般运用过程 一、镜像&#xff08;Image&#xff09;操作 镜像是容器的基础模板&#xff0c;存储在本地或远程仓库中。 1. 镜像拉取 # 从指定镜像源拉取 docker pull docker.m.daocloud.io/library/nginx 2. 镜像查看 # 列出本地镜像 docker images # 或 docker image…

多个参数用websocket 向io 服务器发送变量,一次发一个,并接收响应

问题&#xff1a;多个参数用websocket 向io 服务器发送变量&#xff0c;一次发一个&#xff0c;并接收响应&#xff0c;如果是多个变量&#xff0c;但还是需要一个个发送&#xff0c;应该怎么实现&#xff0c;思路是什么样子的呢&#xff1f;用数组的话&#xff0c;应该怎么用&…

Flink-05学习 接上节,将FlinkJedisPoolConfig 从Kafka写入Redis

上节成功实现了FlinkKafkaConsumer消费Kafka数据&#xff0c;并将数据写入到控制台&#xff0c;接下来将继续将计算的结果输入到redis中。 pom.xml 引入redis到pom包 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://mave…

git教程-pycharm使用tag打标签

一.生成tag标签 前言 当我们的代码完成了第一阶段的需求&#xff0c;版本稳定后&#xff0c;希望能出个稳定版本。于是在 commit 后需要打个 tag 标签&#xff0c;也就是我们平常说的版本号&#xff0c;如v1.0版本 本篇讲解如何使用 pycharm 打 tag 标签&#xff0c;并推送到…

PHP Error: 深入解析与处理技巧

PHP Error: 深入解析与处理技巧 引言 PHP作为一种广泛使用的服务器端脚本语言,在Web开发领域占据着重要地位。然而,任何编程语言都难以避免错误的发生。本文将深入探讨PHP错误处理的相关知识,包括错误类型、错误显示、错误日志以及错误处理技巧,帮助开发者更好地应对和解…

21、企业行政办公(OA)数字化转型:系统如何重塑企业高效运营新范式

企业行政办公是营造高效工作环境、提升员工幸福感和归属感的重要基石&#xff0c;更是传递组织温度与价值关怀的第一窗口。在数字化转型浪潮席卷各行各业的今天&#xff0c;企业行政办公领域正经历一场静默但深刻的变革。据统计&#xff0c;采用智能化OA系统的企业&#xff0c;…

基于开源AI智能名片链动2+1模式S2B2C商城小程序的抖音渠道力拓展与多渠道利润增长研究

摘要&#xff1a;在数字化商业竞争日益激烈的背景下&#xff0c;抖音平台凭借其庞大的流量基础和兴趣电商生态&#xff0c;成为品牌增长的关键阵地。渠道力作为品牌增长的核心驱动力&#xff0c;以抖音势能为内核&#xff0c;通过流量与销量的外溢效应&#xff0c;可显著提升品…

基于二维码的视频合集高效管理与分发技术

一、 视频资源聚合的技术挑战与解决方案 在企业培训、在线教育和产品展示等场景中&#xff0c;视频资源的结构化组织与高效分发始终是技术实现的核心挑战。传统方案往往面临三大痛点&#xff1a;资源碎片化导致的管理混乱、多视频序列播放的用户体验不佳、以及跨平台兼容性问题…

GPT-2论文阅读:Language Models are Unsupervised Multitask Learners

本文解析 OpenAI 2019 年发布的里程碑式论文&#xff0c;该论文首次提出了 GPT-2 模型&#xff0c;揭示了语言模型作为无监督多任务学习器的革命性潜力。文章的核心观点是&#xff1a;语言模型在无监督训练过程中&#xff0c;可以隐式地学习多种任务&#xff0c;无需特定任务微…