C++仿muduo库onethreadoneloop高并发服务器

一.基本设计与模块

复制代码
class Buffer
{
private:
    std::vector<char> _buffer;
    uint64_t _reader_idx; // 读偏移量
    uint64_t _write_idx;  // 写偏移量
}

class Socket
{
private:
    int _sockfd;
}

class Channel
{
private:
    int _fd;
    uint32_t _events;
    uint32_t _revents;
    EventLoop *_loop;
    using EventCallback = std::function<void()>;
    EventCallback _read_callback;  // 可读回调
    EventCallback _write_callback; // 可写回调
    EventCallback _error_callback; // 错误事件回调
    EventCallback _close_callback; // 连接断开回调
    EventCallback _event_callback; // 任意事件回调
}
class Poller
{
private:
    int _epfd;
    struct epoll_event _evs[MAX_EPOLLEVENTS];
    std::unordered_map<int, Channel *> _channels;
}

class Timertask
{
private:
    uint64_t _id;
    uint32_t _timeout; // 定时器超时时间
    TaskFunc _task_cb; // 定时器执行定时任务
    bool _cancel;
    ReleaseFunc _release; // 删除时间轮中定时器对象信息
}
class Timerwheel
{
private:
    using WeakTask = std::weak_ptr<Timertask>;
    using PtrTask = std::shared_ptr<Timertask>;
    int _tick; // 秒针走向
    int _capacity;
    std::vector<std::vector<PtrTask>> _wheel;
    std::unordered_map<uint64_t, WeakTask> _timers; // 记录定时器任务
    int _timerfd;
    EventLoop *_loop;
    std::unique_ptr<Channel> _timer_channel;
}

class EventLoop
{
private:
    using Functor = std::function<void()>;
    std::thread::id _thread_id;
    int _event_fd;
    std::unique_ptr<Channel> _event_channel;
    Poller _poller;
    std::vector<Functor> _tasks;
    std::mutex _mutex;
    Timerwheel _tw;
}

class Any
{
private:
    class holder
    {
    public:
        virtual ~holder() {}
        virtual const std::type_info &type() = 0;
        virtual holder *clone() = 0;
    };
    template <class T>
    class placeholder : public holder
    {
    public:
        placeholder(const T &val) : _val(val) {}
        virtual const std::type_info &type()
        {
            return typeid(T);
        }
        virtual holder *clone()
        {
            return new placeholder(_val);
        }

    public:
        T _val;
    };
    holder *_content;
}

class LoopThread
{
private:
    std::mutex _mutex;
    std::condition_variable _cond;
    EventLoop *_loop;
    std::thread _thread;
}

class LoopThreadPool
{
private:
    int _thread_count; // 线程数量
    int _next_idx;     // 下标
    EventLoop *_baseloop;
    std::vector<LoopThread *> _threads;
    std::vector<EventLoop *> _loops;
}

class Connection : public std::enable_shared_from_this<Connection>
{
private:
    uint64_t _conn_id;             // connection标识id,同时作为计时器id
    int _sockfd;                   // 连接描述符
    bool _enable_inactive_release; // 是否启动 非活跃销毁的判断符
    EventLoop *_loop;
    ConnStatu _statu;
    Socket _socket;
    Channel _channel;
    Buffer _in_buffer;
    Buffer _out_buffer;
    Any _context; // 上下文接受
    using ConnectionCallback = std::function<void(const PtrConnection &)>;
    using MessageCallback = std::function<void(const PtrConnection &, Buffer *)>;
    using ClosedCallback = std::function<void(const PtrConnection &)>;
    using AnyEventCallback = std::function<void(const PtrConnection &)>;
    ConnectionCallback _connection_callback;
    MessageCallback _message_callback;
    ClosedCallback _closed_callback;
    ClosedCallback _server_closed_callback;
    AnyEventCallback _anyevent_callback;
}

class Acceptor
{
private:
    Socket _socket;
    EventLoop *_loop;
    Channel _channel;

    using AcceptCallback = std::function<void(int fd)>;
    AcceptCallback _accept_callback;
}

class TcpServer
{
private:
    uint64_t _conn_id; // 自增id
    int _timeout;      // 非活跃限制时间
    int _port;
    bool _enable_inactive_release; // 是否启动非活跃连接标准
    EventLoop _baseloop;
    Acceptor _acceptor; // 监听套接字管理对象
    LoopThreadPool _pool;
    std::unordered_map<uint64_t, PtrConnection> _conns; // 保存connection对象
    using Functor=std::function<void()>;
    using ConnectionCallback = std::function<void(const PtrConnection &)>;
    using MessageCallback = std::function<void(const PtrConnection &, Buffer *)>;
    using ClosedCallback = std::function<void(const PtrConnection &)>;
    using AnyEventCallback = std::function<void(const PtrConnection &)>;
    ConnectionCallback _connection_callback;
    MessageCallback _message_callback;
    ClosedCallback _closed_callback;
    ClosedCallback _server_closed_callback;
    AnyEventCallback _anyevent_callback;
}


//httpserver 模块
class Util
{
    static size_t Split(const std::string &str, const std::string &sep,     std::vector<std::string> *arry)
    static bool ReadFile(const std::string &filename, std::string *str)
// 向文件写入内容
    static bool WriteFile(const std::string &filename, const std::string &str)
 // URL编码
    static std::string UrlEncode(const std::string url, bool convert_space_to_plus)
//字符转化
    static char HEXTOI(char c)
// URL解码
    static std::string UrlDecode(const std::string url, bool convert_space_to_plus)
// 响应状态码获取
    static std::string StatuDesc(int statu)
// 文件后缀名获取mime
    static std::string ExMime(const std::string &filename)
// 判断文件是否是目录
    static bool IsDirectory(const std::string &filename)
 // 判断文件是否是普通文件
    static bool IsRegular(const std::string &filename)
// http请求的资源路径有效性判断
    static bool ValidPath(const std::string &path)
}

class HttpRequest
{
public:
    std::string _method;                                   // 请求方法
    std::string _path;                                     // 资源路径
    std::string _version;                                  // 协议版本
    std::string _body;                                     // 请求正文
    std::smatch _matchs;                                   // 资源路径正则表达式提取的数据
    std::unordered_map<std::string, std::string> _headers; // 头部字段
    std::unordered_map<std::string, std::string> _params;  // 查询字符串
}

class HttpResponse
{
public:
    int _statu;
    bool _redirector_flag;
    std::string _body;
    std::string _redirect_url;
    std::unordered_map<std::string, std::string> _headers;
}

class HttpContext//对请求内容解析
{
private:
    int _resp_statu;           // 响应状态码
    HttpRecvStatu _recv_statu; // 接受请求的解析状态
    HttpRequest _request;      // 接受的请求
}

class HttpServer{//完成响应报文 以及静态或动态资源获取处理的实现
    private:
    std::string _basedir;
        using Handler=std::function<void(const HttpRequest&,HttpResponse*)>;
         using Handlers= std::vector<std::pair<std::regex,Handler>>;
        Handlers _get_route;
        Handlers _post_route;
        Handlers _put_route;
        Handlers _delete_route;
        TcpServer _server;
}

二.Buffer类与时间轮类Any任意类的设计

Buffer:Buffer类用于对socket接受的客户端消息进行缓存。

TimerWheel:对于定时任务添加并到时执行,并用于超时未响应的断开连接功能。

Any:用于存储任意对象,主要用于存储请求报文。

TimerWheel设计:

主要是对Connection连接进行的超时管理,如果超时即销毁

timerwheel内部有一个timerid是linux系统提供的定时器,用于定时功能,并有一个Channel对象用于对timerwheel回调任务的监听,每当timerfd进行一步,都会触发监听的可读回调,进行对时间轮内部tick刻钟移动。

Tick移动与任务执行设计:timertask由智能指针管理,timerwheel内部hash管理任务weakptr,而时间轮变量存储任务share_ptr,时间轮走向的当前节点会clear当前存储的share_ptr,如果指针被完全释放,则通过timertask的析构函数执行设定的任务,所以timerwheel只需要向后添加share_ptr,就可以推迟timertask任务执行,实现定时销毁的刷新机制

Any类设计:

复制代码
  class holder
    {
    public:
        virtual ~holder() {}
        virtual const std::type_info &type() = 0;
        virtual holder *clone() = 0;
    };
    template <class T>
    class placeholder : public holder
    {
    public:
        placeholder(const T &val) : _val(val) {}
        virtual const std::type_info &type()
        {
            return typeid(T);
        }
        virtual holder *clone()
        {
            return new placeholder(_val);
        }

    public:
        T _val;
    };
    holder *_content;

通过c++继承机制,用父类指针指向子类对象,子类存储对应存储的数据,通过模板实现存储任意类型的类

三.Channel Poller与Eventloop的关联

接口与成员变量

Channel用于对事件监控的管理,监控实现由Poller提供,EventLoop对应一个单线程任务处理,Start()开始任务的处理,同时保证任务执行在单线程内。

Channel bind对应的read write error等事件回调的对应函数调用,epoll_wait事件由start进行处理,延迟执行和跨线程任务 放入任务队列等待执行,并由event_fd用于唤醒epoll_wait避免阻塞,防止队列任务无法执行

三.Loop线程创建与线程管理

loop线程创建后直接在创建线程内循环执行Start其对应的EventLoop

复制代码
private:
    void ThreadEntry()
    {
        EventLoop loop;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _loop = &loop; // loop有值了直接唤醒阻塞
            _cond.notify_all();
        }
        loop.Start();
    } // 实例化eventloop对象,并运行eventloop模块

四.Connection Acceptor TcpServer类

每一个连接都会被分配一个线程EventLoop,服务器可以自定义线程数量,线程轮询分配保证线程均衡,Connection使用share_ptr管理,设定超时清理connecion资源,TcpServer存储所有的Connection智能指针,并由TcpServer启动监听建立三次握手。

Acceptor用于获取连接,在Tcpserver内调用。

四.httpserver和工具类介绍

工具类:字符串分割,文件读写,Url解码与Url编码,Http状态码描述,MIME类型获取,文件类型判断,路径有效性验证

HttpServer主要实现对请求报文的处理与响应报文的返回

五.Reactor模型优势

采用单EventLoop单线程架构,通过实现高并发服务器组件可构建高性能服务器。

主Reactor接收新连接后,将其分配给子Reactor进行通信事件监控。各子Reactor线程负责监控各自描述符的读写事件,执行数据读写和业务处理操作。

采用单EventLoop单线程架构,通过实现高并发服务器组件可构建高性能服务器。

主Reactor接收新连接后,将其分配给子Reactor进行通信事件监控。各子Reactor线程负责监控各自描述符的读写事件,执行数据读写和业务处理操作。
单线程单循环的设计理念是将所有操作集中在一个线程内处理,每个线程对应一个独立的事件处理循环。

单线程单循环的设计理念是将所有操作集中在一个线程内处理,每个线程对应一个独立的事件处理循环。

核心:每一个EventLoop都有其单独对应的一个线程,每一个建立的连接都有一个Channel事件监控模块,每一个Channel对应一个EventLoop,也就是每一个连接都有一个线程为其服务,一个线程可能对应多个Connection连接。事件触发调用对应的回调函数,非当前线程添加的任务会被放入任务队列,并唤醒其Epoll_wait,并由其对应的线程执行。也就实现了多线程对Connection的处理,实现高并发单EventLoop单线程的架构。

代码仓库链接: 江离池雨/单线程单EventLoop高并发服务器组件

相关推荐
虾..2 小时前
Linux 信号发送和保存
linux·运维·服务器
Bruce_kaizy2 小时前
c++图论——最短路之Johnson算法
开发语言·数据结构·c++·算法·图论
乾元2 小时前
AI 在云网络(VPC / VNet)部署的编排与安全对齐——从“手工堆资源”到“意图驱动的网络生成”(含 Terraform 工程化)
运维·网络·人工智能·网络协议·安全·云计算·terraform
盛满暮色 风止何安2 小时前
负载均衡的部署模式
运维·服务器·网络·网络安全·负载均衡
Meaauf2 小时前
华为 | 二层隧道协议L2TP实验
网络·华为
CQ_YM2 小时前
网络编程之UDP
linux·c语言·网络·单片机·udp
程序员洲洲2 小时前
2025年远程控制软件排行榜:安全性能哪家强?ToDesk/TeamViewer/向日葵等对比
服务器·安全·远程控制
weixin199701080162 小时前
TikTokitem_search_video关键词视频列表接口对接全攻略:从入门到精通
java·服务器·音视频
qqssss121dfd2 小时前
计算机网络(第8版,谢希仁)第四章习题解答
服务器·c语言·网络·单片机·计算机网络