仿Muduo库实现高并发服务器——事件监控Poller模块

Poller模块在整个项目的使用

下面代码是对I/O复用接口函数的基本使用。

回顾上篇文章:事件监控管理模块

这个模块是将触发事件的描述符,给到外面,让外面去做对应的处理。

cpp 复制代码
#define MAX_EPOLLEVENTS 1024
class Poller {
    private:
        int _epfd;
        struct epoll_event _evs[MAX_EPOLLEVENTS];
        std::unordered_map<int, Channel *> _channels;
    private:
        //对epoll的直接操作
        void Update(Channel *channel, int op) {
            // int epoll_ctl(int epfd, int op,  int fd,  struct epoll_event *ev);
            int fd = channel->Fd();
            struct epoll_event ev;
            ev.data.fd = fd;
            ev.events = channel->Events();
            int ret = epoll_ctl(_epfd, op, fd, &ev);
            if (ret < 0) {
                ERR_LOG("EPOLLCTL FAILED!");
            }
            return;
        }
        //判断一个Channel是否已经添加了事件监控
        bool HasChannel(Channel *channel) {
            auto it = _channels.find(channel->Fd());
            if (it == _channels.end()) {
                return false;
            }
            return true;
        }
    public:
        Poller() {
            _epfd = epoll_create(MAX_EPOLLEVENTS);
            if (_epfd < 0) {
                ERR_LOG("EPOLL CREATE FAILED!!");
                abort();//退出程序
            }
        }
        //添加或修改监控事件
        void UpdateEvent(Channel *channel) {
            bool ret = HasChannel(channel);
            if (ret == false) {
                //不存在则添加
                _channels.insert(std::make_pair(channel->Fd(), channel));
                return Update(channel, EPOLL_CTL_ADD);
            }
            return Update(channel, EPOLL_CTL_MOD);
        }
        //移除监控
        void RemoveEvent(Channel *channel) {
            auto it = _channels.find(channel->Fd());
            if (it != _channels.end()) {
                _channels.erase(it);
            }
            Update(channel, EPOLL_CTL_DEL);
        }
        //开始监控,返回活跃连接
        void Poll(std::vector<Channel*> *active) {
            // int epoll_wait(int epfd, struct epoll_event *evs, int maxevents, int timeout)
            int nfds = epoll_wait(_epfd, _evs, MAX_EPOLLEVENTS, -1);
            if (nfds < 0) {
                if (errno == EINTR) {
                    return ;
                }
                ERR_LOG("EPOLL WAIT ERROR:%s\n", strerror(errno));
                abort();//退出程序
            }
            for (int i = 0; i < nfds; i++) {
                auto it = _channels.find(_evs[i].data.fd);
                assert(it != _channels.end());
                it->second->SetREvents(_evs[i].events);//设置实际就绪的事件
                active->push_back(it->second);
            }
            return;
        }
};
相关推荐
小杨不想秃头3 小时前
信息安全工程师教程第二章密码学
运维·服务器·密码学
I'mChloe3 小时前
WGCLOUD怎么监控多台服务器?从Server、Agent 部署到监控面板实战
运维·服务器
Android系统攻城狮3 小时前
Linux PipeWire深度解析之pw_init调用流程与实战(八十三)
linux·运维·服务器·音频进阶·pipewire音频进阶
zbyyd5 小时前
Linux 进程管理详解:从概念到实战
linux·运维·服务器
云飞云共享云桌面7 小时前
智能装备工厂研发团队如何利用单台服务器承载 10 路 SolidWorks 并发?
运维·服务器·3d·自动化·制造
辻弋2017 小时前
手动关服务会自动重启、组策略家庭版用不了——Windows Update Blocker用“禁用+锁定”双保险,让Win10/11自动更新彻底闭嘴
服务器·人工智能·windows·电脑·开源软件
躺不平的理查德7 小时前
OpenSSL 的异步 TLS 1.3 加密
linux·运维·服务器
tedcloud1237 小时前
Awesome DSH Plugin 怎么用?给 DeepSeek Harness 搭建自己的插件生态
大数据·linux·服务器·人工智能·音视频
夜月yeyue8 小时前
SOME/IP 服务模型
linux·服务器·单片机·安全·车载系统
程序员z78 小时前
深入理解 GMP 模型:Go 协程调度器的设计与调度场景全解析
服务器·网络·golang