cpp-httplib 源码剖析
cpp-httplib是一个c++封装的http开源库,仅包含一个头文件,不过代码行数达到8000多行,相比于上一节中讲述的Tinyhttpd ,该库功能就比较完善,并且可以在简单的项目中使用。
cpp-httplib 服务端采用select IO多路复用模型,工作线程池的处理方式,主要包含的类Server、Client、Request、Response。
1 简单举例
1.1 服务端举例
httplib::Server server;
auto hello = [](const httplib::Request & req, httplib::Response & rsp) {
rsp.status = 200;
rsp.set_content("<html><h1> hello cpp-httplib!</h1></html>", "text/html");
};
server.Get("/", hello);
server.listen("0.0.0.0", 9000);
1.2 客户端举例
httplib::Client client("127.0.0.1", 9000);
auto result = client.Get("/");
std::cout << result->status << std::endl;
std::cout << result->body << std::endl;
上述进行简单的举例,方便掌握处理流程。借助该库还可以实现http推送功能,更多应用可以参考库中自带的例子。
2 整体流程分析
2.1 服务端Server 分析

图中描述了整体流程,基本包含了服务端的主要处理步骤。
a 搭建tcp服务,注册资源路径与处理方法,并开启监听。
b 创建工作线程,select循环监听,当收到客户端消息,放入jobs中,通知工作线程处理。
c 工作线程从jobs中取出待处理请求。
d 处理请求,包含校验、协议解析、根据请求方式分发,最终调用用户注册方法处理上层业务。
2.2 客户端Client 分析

客户端借助类ClientImpl,完成socket初始化,请求下发与解析响应。
2.3 辅助类 Request、Response
struct Request {
std::string method; //请求方式
std::string path; //资源路径
Headers headers; //请求头属性,键值对方式
std::string body; //请求体}
struct Response {
std::string version; //响应版本int status; //响应状态
Headers headers; //响应头
std::string body; //响应体}
Request、Response 分别用来组装HTTP消息请求体与消息响应体 ,HTTP结构可参考如下:


3 测试
增加了日志打印,配置两个工作线程,从日志可以看出主线程[48280]循环select监听,两个工作线程处理客户端请求。


附:
1 自定义日志接口:可显示时间以及线程id。
#include <stdio.h>
#include <time.h>
#include <thread>
#include <iostream>
template <typename... Args>
void print_log(const char* fmt, Args... args) {
char log_buf[4096] = { 0 };
snprintf(log_buf, 4096, fmt, args...);
time_t time_data = time(NULL);
tm cur_time;
localtime_s(&cur_time, &time_data);
char time_buf[64] = { 0 };
snprintf(time_buf, 64, "%02d:%02d:%02d",
cur_time.tm_hour,
cur_time.tm_min,
cur_time.tm_sec);
int tid = (*(int*)&std::this_thread::get_id());
char buf[5120] = { 0 };
snprintf(buf, 5120, "[%s] [%d] [%s]", time_buf, tid, log_buf);
std::cout << buf << std::endl;
}
2 源码路径
https://github.com/yhirose/cpp-httplib
https://github.com/yhirose/cpp-httplib
更多推荐
所有评论(0)