C++仿muduo库高并发服务器项目:Poller模块

前言

本篇文章所讲的是本人的个人项目仿muduo库高并发服务器中的Poller模块实现部分。

Poller模块介绍:

这也是一个比较简单的基础功能模块,主要提供对epoll系统调封装的接口。

  • 功能:对任意描述符进行IO事件监控
  • 意义:封装epoll,简化描述符事件监控操作
  • 功能接口:
    1. 添加事件监控(针对Channel模块 )
    2. 修改事件监控
    3. 移除事件监控

Channel模块启用监控、移除监控等功能,都是通过调用该模块的封装完成的。

模块设计

  1. 需具备 epoll 的操作句柄。
  2. 拥有 struct epoll_event 结构数组,用于监控时保存所有活跃事件。
  3. 利用哈希表管理描述符及其对应的事件管理 Channel 对象。

逻辑流程

  1. 对描述符进行监控,通过 Channel 明确描述符需要监控的事件。
  2. 当描述符就绪时(描述符有事件就绪时),借助哈希表根据描述符找到对应的 Channel(通过 Channel 确定事件的处理方式),并返回就绪描述符对应的 Channel
c++ 复制代码
const int MAX_EPOLLEVENTS = 1024;
class Poller
{
private:
    int _epfd;                                      //epoll文件描述符
    struct epoll_event _evs[MAX_EPOLLEVENTS];       //存放就绪事件的数组
    std::unordered_map<int,Channel*> _channels;     //建立epfd到channel指针的映射

    //对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!!");
        }
    }
    //判断一个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));
            Update(channel,EPOLL_CTL_ADD);
        }
        //存在则修改
        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",strerror(errno));
            abort();
        }

        for(int i = 0;i < nfds;i++)
        {
            auto it = _channels.find(_evs[i].data.fd);
            assert(it != _channels.end());
            it->second->SetEvents(_evs[i].events);//设置实际就绪事件
            active->push_back(it->second);
        }
    }
};
相关推荐
嵌入式-老费9 小时前
vivado hls的应用(带ddr读取的ip)
服务器·网络·tcp/ip
weixin_462901979 小时前
ESP32电压显示
开发语言·javascript·css·python
不知名。。。。。。。。9 小时前
仿muduo库实现高并发服务器----HttpServer
运维·服务器·算法
探序基因9 小时前
R语言读取单细胞转录组基因表达矩阵loom文件
开发语言·r语言
大尚来也9 小时前
高并发架构下的缓存“三座大山”:穿透、雪崩与击穿的深度突围
开发语言
暮冬-  Gentle°9 小时前
移动设备上的C++优化
开发语言·c++·算法
IMPYLH9 小时前
Linux 的 dd 命令
linux·运维·服务器
2401_874732539 小时前
C++中的装饰器模式高级应用
开发语言·c++·算法
lars_lhuan9 小时前
Go atomic
开发语言·后端·golang
lly2024069 小时前
《Foundation 分页》
开发语言