📟作者主页:慢热的陕西人
🌴专栏链接:C++云备份项目
📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言
主要内容介绍了第三方库httplib的一些内容,以及实现了一个简单的CS例子
文章目录
- 云备份day03
- 1.httplib库
- 2.httplib实现server和client
- 2.1httplib实现server端
- 2.2httplib实现client端
云备份day03
1.httplib库
httplib 库,一个 C++11 单文件头的跨平台 HTTP/HTTPS 库。安装起来非常容易。只需包含 httplib.h 在你的代码
中即可。
httplib 库实际上是用于搭建一个简单的 http 服务器或者客户端的库,这种第三方网络库,可以让我们免去搭建服
务器或客户端的时间,把更多的精力投入到具体的业务处理中,提高开发效率。
namespace httplib
{
struct MultipartFormData
{
std::string name;
std::string content;
std::string filename;
std::string content_type;
};
using MultipartFormDataItems = std::vector<MultipartFormData>;
struct Request
{
std::string method; //请求方法
std::string path; //url
Headers headers; //头部字段
std::string body; //正文->有效载荷
// for server
std::string version;//协议版本
Params params; //查询字符串
MultipartFormDataMap files;//保存的是客户端上传文件的信息
Ranges ranges; //用于实现断点续传的文件请求的区间
bool has_header(const char *key) const;
std::string get_header_value(const char *key, size_t id = 0) const;
void set_header(const char *key, const char *val);
bool has_file(const char *key) const;
MultipartFormData get_file_value(const char *key) const;
};
struct Response
{
std::string version; //协议版本
int status = -1; //响应状态码
std::string reason; //
Headers headers; //头部字段
std::string body; //响应给客户端的正文
std::string location; // Redirect location
void set_header(const char *key, const char *val); //设置头部字段
void set_content(const std::string &s, const char *content_type); //设置正文
};
class Server
{
using Handler = std::function<void(const Request &, Response &)>; //函数指针类型
using Handlers = std::vector<std::pair<std::regex, Handler>>; //请求与处理函数的映射表
std::function<TaskQueue *(void)> new_task_queue; //线程池---用于处理请求
Server &Get(const std::string &pattern, Handler handler); //针对某种请求方法的某个请求设定
Server &Post(const std::string &pattern, Handler handler); //映射的处理函数
Server &Put(const std::string &pattern, Handler handler); //
Server &Patch(const std::string &pattern, Handler handler);
Server &Delete(const std::string &pattern, Handler handler);
Server &Options(const std::string &pattern, Handler handler);
bool listen(const char *host, int port, int socket_flags = 0); //搭建并启动http服务器
};
//用于搭建http客户端
class Client
{
Client(const std::string &host, int port); //传入服务器的ip地址和端口
Result Get(const char *path, const Headers &headers); //向服务器发送get请求
Result Post(const char *path, const char *body, size_t content_length,
const char *content_type);
Result Post(const char *path, const MultipartFormDataItems &items); //post请求提交多区域数据,常用于多文件上传
}
}
Request
Request结构体的作用:
1.客户端保存的所有http请求相关信息,最终组织http请求发送给服务器
2.服务器收到http请求之后进行解析,将解析的数据保存在 Request结构体内部,待后续处理Response
Response结构体的作用:
用户将响应数据放到结构体中,httplib会将其中的数据按照http响应的格式组织成http响应
然后发送给客户端Server:
server类的功能:用于搭建http的服务器
**1.hander 函数指针类型:**定义了一个http请求处理回调函数的方式
函数指针类型:定义了一个http请求处理回调函数格式httplib搭建的服务器收到请求后,进行解析,得到一Reques结构体:其中包含了请求数据根据请求数据我们就可以处理这个请求了,这个处理函数定义的格式就是Handler格式
void(const Request &,Response &)
Request参数,1保存请求数据,让用户能够根据请求数据进行业务处理。
Response参数,需要用户在业务处理中,填充数据,最终要响应给客户端
2.Handlers 是一个请求路由数组:
其中包含两个信息std::vector<std::pair<std::regex,Handler>>
regex:正则表达式-用于匹配http请求资源路径
Handler:请求处理函数指针可以理解,Handlers是一张表,映射了一个客户端请求的资源路径和一个处理函数(用户自己定义的函数)
当服务器收到请求解析得到Request就会根据资源路径以及请求方法到这张表中查看有没有对应的处理函数
如果有则调用这个函数进行请求处理,无则响应404.**处理流程:**线程池,处理http请求
httplib收到一个新建链接,则将新的客户端连接抛入到线程池中
线程池中线程的工作:
①接收请求,解析请求,得到Request结构体也就是请求的数据
②在Handlers映射表中,根据请求信息查找处理函数,如果有则调用函数处理
void(const Request &, Response &) ③当处理函数调用完毕根据函数返回的Response结构体中的数据组织http响应发送给客户端
2.httplib实现server和client
2.1httplib实现server端
#include"httplib.h"
using namespace std;
using namespace httplib;
// 处理 "/hi" 路径的 GET 请求,返回 "hello_world!"
void Hello(const Request& req, Response& rsp)
{
rsp.set_content("hello_world!", "text/plain");
rsp.status = 200;
}
// 处理 "/numbers/{num}" 路径的 GET 请求,返回匹配到的数字
void Numbers(const Request& req, Response& rsp)
{
auto num = req.matches[1]; // 0 保存的是整体的 path,往后的下标中保存的是数据
rsp.set_content(num, "text/plain");
rsp.status = 200;
}
// 处理 "/multipart" 路径的 POST 请求,返回上传的文件名和内容
void Multipart(const Request& req, Response& rsp)
{
auto ret = req.has_file("file");
if (ret == false)
{
cout << "not file upload" << endl;
rsp.status = 400;
return;
}
const auto& file = req.get_file_value("file");
rsp.body.clear();
rsp.body = file.filename; // 文件名称
rsp.body += "\n";
rsp.body += file.content; // 文件内容
rsp.set_header("Content-Type", "text/plain");
rsp.status = 200;
return;
}
int main()
{
Server server; // 实例化一个 server 对象用于搭建服务器
server.Get("/hi", Hello); // 注册一个针对 "/hi" 的 GET 请求的处理函数映射关系
server.Get(R"(/numbers/(\d+))", Numbers);
server.Post("/multipart", Multipart);
server.listen("0.0.0.0", 9090);
return 0;
}
2.2httplib实现client端
#include"httplib.h" // 引入 httplib 库的头文件
using namespace std; // 使用标准命名空间
#define SERVER_IP "117.72.37.100" // 定义服务器 IP 地址常量
#define SERVER_PORT 9090 // 定义服务器端口号常量
int main()
{
// 实例化一个 httplib 客户端对象,并指定服务器的 IP 地址和端口号
httplib::Client client(SERVER_IP, SERVER_PORT);
// 创建一个多部分表单数据项
httplib::MultipartFormData item;
item.name = "file"; // 表单项的名称
item.filename = "hello.text"; // 文件名
item.content = "hello world"; // 文件内容
item.content_type = "text/plain"; // 文件内容类型
// 创建一个多部分表单数据项列表,并将上面创建的表单项添加到列表中
httplib::MultipartFormDataItems items;
items.push_back(item);
// 向服务器发送 POST 请求,提交多部分表单数据
auto res = client.Post("/multipart", items);
// 输出服务器响应的状态码和响应体
cout << res->status << endl; // 打印响应状态码
cout << res->body << endl; // 打印响应体内容
return 0;
}
到这本篇博客的内容就到此结束了。
如果觉得本篇博客内容对你有所帮助的话,可以点赞,收藏,顺便关注一下!
如果文章内容有错误,欢迎在评论区指正