1.7.C++项目:仿muduo库实现并发服务器之Poller模块的设计

项目完整在:

文章目录

一、Poller模块:描述符IO事件监控模块

二、提供的功能

对任意的描述符进行IO事件监控。

三、实现思想

(一)功能

对任意的描述符进行IO事件监控。

(二)意义

对epoll进行的封装,让对描述符进行事件监控的操作更加简单。

(三)功能设计

  1. 添加事件监控------ channel模块
  2. 修改事件监控
  3. 移除事件监控
  4. 取消定时任务

四、封装思想

cpp 复制代码
封装思想: 1. 必须拥有一个epoll的操作句柄
         2. 拥有一个struct epoll_event 结构数组,监控保存所有的活跃事件!
         3. 使用hash表管理描述符与描述符对应的事件管理Channnel对象!
逻辑流程:
         1. 对描述符进行监控,通过Channnel才能知道描述符监控什么事件
         2. 当描述符就绪了,通过描述符在hash表中找到对应的Channel(得到了Channel才知道什么事件如何处理)当描述符就绪了,返回就绪描述符对应的Channel

五、代码

(一)框架

cpp 复制代码
框架:
class Poller {
private:
        int _epfd;
        struct epoll_event_evs[xxx];
        std::unordered_map<int,Channel*> mp;
private:
        // 1. 判断要更新事件的描述符是否存在
        // 2. 针对epoll直接操作(添加,修改,移除)
public:
        // 1. 添加或者更新描述符所监控的事件
        void Update(Channel* channel);
        // 2. 移除描述符所监控的事件
        void Remove(Channel* )
        // 3. 开始监控,获取就绪Channel
};
*/
/*

(二)完整代码

cpp 复制代码
#define MAX_EPOLLEVENTS 1024
// Poller模块是对epoll进⾏封装的⼀个模块,主要实现epoll的IO事件添加,修改,移除,获取活跃连接功能。
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 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!!!");
                        abort(); // 推出程序!!
                }
        }
        // 判断一个Channel是否已经添加到了事件监控
        bool hashChannel(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 = hashChannel(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;
        }
};
相关推荐
2401_850410838 分钟前
文件系统和日志管理
linux·运维·服务器
老猿讲编程14 分钟前
一个例子来说明Ada语言的实时性支持
开发语言·ada
UestcXiye1 小时前
《TCP/IP网络编程》学习笔记 | Chapter 3:地址族与数据序列
c++·计算机网络·ip·tcp
Chrikk1 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*1 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue1 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man1 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
一只哒布刘2 小时前
NFS服务器
运维·服务器
霁月风2 小时前
设计模式——适配器模式
c++·适配器模式
萧鼎3 小时前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步