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


    项目完整在:

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

    在这里插入图片描述

    二、提供的功能

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

    三、实现思想

    (一)功能

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

    (二)意义

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

    (三)功能设计

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

    四、封装思想

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

    五、代码

    (一)框架

    框架:
    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
    };
    */
    /*
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    (二)完整代码

    #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;
            }
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
  • 相关阅读:
    释放锁流程源码剖析
    【毕业设计】深度学习中文情感分类(情感分析) - python 卷积神经网络
    Unity实现跨场景的传送门
    基于uwb和IMU融合的三维空间定位算法matlab仿真
    Cisco跨站请求伪造漏洞
    【图像去噪】基于PM模型实现图像降噪附matlab代码
    Gradle国内腾讯镜像
    STM32F103 USART1 IDLE FLAG
    ciscn 2022 华东北分区赛pwn duck
    JavaScript While循环
  • 原文地址:https://blog.csdn.net/weixin_54447296/article/details/133497920