一.基本设计与模块
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高并发服务器组件