文章目录

    • 前言
    • `cpp-http` 库简介
    • `cpp-http` 库使用介绍
      • http 客户端搭建步骤
      • http 服务端搭建步骤
    • `cpp-http` 库示例
      • 服务端实现
      • 客户端实现
    • 示例下载
  • 参考资料

前言

最近在做的一个项目需要使用到 HTTP 协议,在网上查了很久,也结合了之前学长做的项目,发现 cpp-http 库使用挺多的,所以就边学边做笔记,顺便分享出来(我觉得知识之所以叫知识,就是因为它能被记录并能被传播,为人所知,为人所识)。

我准备把这个学习记录做成一个系列文章,这个系列里面,我会介绍从 HTTP 协议诞生到目前的一些大概情况,然后会简单介绍一下目前 C/C++ 下面用的比较广泛的 HTTP 库,之后就是讲解 cpp-http 库的简单使用、 cpp-http 库的实现,最后如果时间允许的话可以自己手码一个 C 语言的 http 用来作总结。

反正 flag 在这里先立下了,这篇文章是这个系列的第一篇,但是并不是按顺序来的第一篇,这里讲的是 cpp-http 库的简单使用,按顺序来看的话应该是系列里面的第三篇或者第二篇。如果大家目前对 HTTP 协议基础知识有需求的话还请移步其他博主的文章,之后我也会陆续把各个模块补上(下一篇可能是 cpp-http 库的实现部分),敬请大家期待。

另:本人目前是大学生,新人一枚,文章之中难免会有纰漏,还请大家多多包涵,不吝赐教。

cpp-http 库简介

  1. cpp-http 库是什么?
    cpp-http 由是一位国外程序员 yhirose 在 github 上面开源的一个 C++ 项目,同时这个项目得到了世界各地程序员的支持,目前包括原作者在内共有 104 位贡献者,拥有 5.7k Star 和 1.2k Fork,是目前使用较为广泛的一个 C++ http库之一。

  2. cpp-http 项目地址
    https://github.com/yhirose/cpp-httplib
    如果网络不好不能访问 github 的话,这里是国内一位程序员搬运到 gitee 上面的项目,内容都是一样的:
    https://gitee.com/zhangkt1995/cpp-httplib?_from=gitee_search

  3. 关于它的简介,这里引用原作者的话:

    A C++11 single-file header-only cross platform HTTP/HTTPS library.

    It’s extremely easy to setup. Just include the httplib.h file in your code!

    NOTE: This is a multi-threaded ‘blocking’ HTTP library. If you are looking for a ‘non-blocking’ library, this is not the one that you want.

    翻译过来就是:

    一个只有头文件的跨平台 HTTP/HTTPS 库。

    简单易用,只需要包含头文件 httplib,h 即可。

    注意:这个库是一个多线程阻塞式 Http 库,如果您需要的是一个非阻塞式的库,这个库并不适合您。

cpp-http 库使用介绍

网上大多数教程都只介绍了使用 cpp-http 库的 GET 请求使用,没有 POST 请求的(其实两者使用一模一样),在这里我也加上了 POST 请求的部分。

http 客户端搭建步骤

  1. 组织http协议格式的请求数据
  2. 搭建tcp客户端
  3. 发送组织好的http请求数据
  4. 等待服务端响应,接收响应数据
  5. 对响应数据的解析

http 服务端搭建步骤

  1. 搭建tcp服务端
  2. 等待接收客户端发送的数据
  3. 按照 http 协议格式,对数据进行解析(格式按照: 请求方法 URL 协议版本\r\n 头部\r\n 正文)
  4. 根据请求的资源路径以及查询字符串以及正文,进行业务处理
  5. 组织http协议格式的响应,返回给客户端(协议版本 状态码 描述\r\n 头部)

cpp-http 库示例

这里我们先用个 demo 来看看 cpp-http 库怎么使用:

首先先建立工程,目录如下:

▶ tree ../http -L 1
../http
├── client.cpp  # 在这里编辑客户端的代码
├── httplib.h   # 这是 cpp-http 库的头文件,server和client都需要包含它
└── server.cpp # 在这里编辑服务端的代码0 directories, 5 files

其中 httplib.h 就是 cpp-http 库的所有内容了,就是这一个头文件;server.cpp 是我们自己的服务端程序, client.cpp 是我们自己的客户端程序。

服务端实现

  1. 代码。相关的解释都在注释里面
#include <iostream>
#include "httplib.h"using Request = httplib::Request;
using Response = httplib::Response;
using Server = httplib::Server;
using Params = httplib::Params;// get 请求中对 "/go" 的处理
void get_go(const Request& req, Response& res)
{// 设置 "/go" 请求返回的内容res.set_content("<html><h1>I'm the king of the world!</h1></html>", "text/html");std::cout << "Received a request of get [go]." << std::endl;
}int main(int argc, char const *argv[])
{// 搭建服务端Server srv;// 这里注册用于处理 get 请求的函数,当收到对应的get请求时,程序会执行对应的函数srv.Get("/go", get_go); // 可能相比 lambda 表达式,刚从 C 语言转过来的同学更熟悉这种形式,这个get调用方式也更简介易懂// 这里注册的处理函数是 C++ 的 lambda 表达式,直接看成传入了一个指针就行了srv.Get("/hi", [&](const Request& req, Response& res){// 设置 get "hi" 请求返回的内容res.set_content("<html><h1>Hello world!</h1></html>", "text/html");std::cout << "Received a request of get [hi]." << std::endl;});srv.Get("/link", [&](const Request& req, Response& res){res.set_content("<html><h1 href=https://baike.baidu.com/item/%E8%A5%BF%E5%8D%8E%E5%A4%A7%E5%AD%A6%E6%9C%BA%E5%99%A8%E4%BA%BA%E8%B6%B3%E7%90%83%E5%8D%8F%E4%BC%9A/22274030>soccer robot</h1></html>", "text/html");std::cout << "Received a request of get [link]." << std::endl;});// POST 请求处理srv.Post("/get_info", [&](const Request& req, Response& res) {res.set_content("<html><h1>Go ahead!</h1></html>", "text/html");std::cout << "Received a request of POST [get_info]." << std::endl;});// 绑定端口,启动监听srv.listen("0.0.0.0", 12345);return 0;
}

这里大家可能有三个疑问:

  • Server::Get()Server::Post() 注册函数的实现机制,收到请到 GET 请求后是怎么执行对应函数的
  • 使用 Server::listen() 启动端口的实现机制
  • lambda 表达式

其中前两点我会在后面解释,关于lambda表达式的部分可能之后会出相应的文章来介绍,在此之前还请各位移步其他关于 lambda 的文章进行学习。

  1. 编译
    cpp-http 库编译时需要使用线程库 pthread
    编译时使用 g++ 直接编译,使用 gcc 编译会报错(毕竟 gcc 是为 C 设计的)

编译时使用命令:

g++ ./server.cpp -lpthread -o sever.out
  1. 执行
    执行服务端程序:
./server.out
  1. 验证服务端:
  • 可以通过 curl 来查看服务端返回的数据
# 示例如下
$ curl http://ip:port/source
# 这里的 ip 是服务端运行所在电脑的ip,可以通过 `ip -a` 来查看
# port 就是我们在服务端里面指定监听的端口
# source 是通过 http 请求的资源,在这里就是 /hi /link /go 那三个。


最后一行 使用 curl http://0.0.0.0:12345/get_info 时没有返回,并且服务器端也没有接收到数据,说明 curl 直接发送 /get_info 并不能用于提交 POST 请求,怎么使用 curl 提交 POST 请求等我之后有时间了再看看。

 ▶ curl http://0.0.0.0:12345/hi  # 这里是请求 /link 资源需要的命令<html><h1>Hello world!</h1></html>% # 这里是服务器回应的数据▶ curl http://0.0.0.0:12345/link<html><h1 href=https://baike.baidu.com/item/%E8%A5%BF%E5%8D%8E%E5%A4%A7%E5%AD%A6%E6%9C%BA%E5%99%A8%E4%BA%BA%E8%B6%B3%E7%90%83%E5%8D%8F%E4%BC%9A/22274030>soccer robot</h1></html>%▶ curl http://0.0.0.0:12345/go<html><h1>I'm the king of the world!</h1></html>%▶ curl http://0.0.0.0:12345/get_info
  • 也可以通过浏览器来查看数据:

通过在浏览器地址栏输入相应的地址来验证 http 服务端,直接在浏览器地址栏填入链接就好了:
例如我在浏览器输入如下地址

http://http://0.0.0.0:12345/hi

结果如图:

  • 如果一切正常的话,服务端的输出是这样:

▶ ./server.out
Received a request of get [link].
Received a request of get [link].
Received a request of get [hi].
Received a request of get [link].
Received a request of get [link].
Received a request of get [go].
Received a request of get [hi].

客户端实现

  1. 代码
#include <iostream>
#include <string>
#include "httplib.h"using Client = httplib::Client;
using string = std::string;int main(int argc, char const *argv[])
{if (argc < 3) {std::cout << "Please input server ip and port" << std::endl;return 0;}string source; // 用于存储资源名称// 创建客户端// argv[1] 是从命令行传入的 ip// argv[2] 是从命令行传入的 portClient cli(argv[1], atoi(argv[2]));// 这里是一个死循环,用于选择需要读取的资源while (true) {std::cout << "Please input the source you want" << "(Or use <CTRL + C> to exit):" << std::endl;// 从命令行获取下一步需要获取的资源名称std::getline(std::cin, source, '\n');// std::cout << source << std::endl;// GET、POST 请求的返回值std::shared_ptr<httplib::Response> res;if (source == "/get_info") {// POST 请求res = cli.Post(source.c_str()); } else {// GET 请求res = cli.Get(source.c_str());}if (res) {if (res->status == 200) { // 获取对应资源成功,输出获取到的信息std::cout << "Recved response from server: \n\r"<< res->body << "\n\r" << std::endl;} else{ // 获取资源失败,输出 http 状态码std::cout << "Request error: " << res->status << "\n\r" << std::endl;}} else { // 发送失败(多半是配置问题)std::cout << "Request GET failed.\n\r" << std::endl;}sleep(1); // 线程休眠}return 0;
}
  1. 编译
  • 编译命令和 编译 server.cpp 是一样的,不过参数要改成 client.cpp
g++ ./client.cpp -lpthread -o client.out
  • 编译完成后的目录:
▶ tree -L 1 ../http
../http
├── client.cpp
├── client.out
├── httplib.h
├── server
├── server.cpp
└── server.out0 directories, 6 files
  1. 执行
  • 执行服务端和客户端程序:
./server.out
  • 执行客户端程序:
▶ ./client.out 0.0.0.0 12345
Please input the source you want(Or use <CTRL + Z> to exit):
/go
Recved response from server:
<html><h1>I'm the king of the world!</h1></html>Please input the source you want(Or use <CTRL + Z> to exit):
/link
Recved response from server:
<html><h1 href=https://baike.baidu.com/item/%E8%A5%BF%E5%8D%8E%E5%A4%A7%E5%AD%A6%E6%9C%BA%E5%99%A8%E4%BA%BA%E8%B6%B3%E7%90%83%E5%8D%8F%E4%BC%9A/22274030>soccer robot</h1></html>Please input the source you want(Or use <CTRL + Z> to exit):
/hi
Recved response from server:
<html><h1>Hello world!</h1></html>Please input the source you want(Or use <CTRL + Z> to exit):
  • 程序执行结果:

示例下载

链接: https://pan.baidu.com/s/1MuBvdDZxaH1KL-FvpwmXRQ
提取码: rm4i

如果大家有兴趣也可以点这个下载链接支持一下

cpp-http 库的使用相关推荐

  1. matlab安装第三方库,Matlab调用cpp+第三方库

    问题描述:Matlab调用CPP不新鲜,无非就是把写好的c语言编译成mex,然后直接调用呗.很多帖子和书都有描述.具体可以参考附录.这里描述的是如何用Matlab调用Opencv库支持的函数.解决方法 ...

  2. linux cpp标准库,标准库以及标准头文件

    源文件通过编译可以生成目标文件(例如 GCC 下的 .o 和 Visual Studio 下的 .obj),并提供一个头文件向外暴露接口,除了保护版权,还可以将散乱的文件打包,便于发布和使用. 实际上 ...

  3. CMake结合PCL库学习(2)

    紧接着上一篇文章 对于PCL 库中的各个模块之间是有相互依赖关系的 其中Common模块是最基础的模块,其中是定义各种数据结构的头文件,所以Common这个模块是不需要依赖性响的,但是IO 模块就是需 ...

  4. cmake 头文件 库文件 路径搜索 CMAKE_INCLUDE_PATH CMAKE_LIBRARY_PATH

    目录 cmake中定义搜索路径 修改环境变量增加搜索路径 FIND 系列指令,通过FIND寻找路径并进行添加 大型开源库路径添加方式 find_package采用两种模式搜索库 路径搜索,这里介绍头文 ...

  5. android 多个c文件编译成一个so,AndroidStudio使用CMakeLists.txt编译多个so库

    对于单个so库编译就不说了,AndroidStudio可以直接生成单个so库编译的模板 对于实际项目中,多用到的是好几个库,下面说一下编译多个so库的情况 TIM图片20180927155108.pn ...

  6. Ubuntu下添加boost库

    @Ubuntu下Boost库的链接 在CmakeLists.txt中添加Boost组件 Boost具有很好的平台独立性,因此可以作为首选api来完成特定功能. 最常用的为filesystem,用来获取 ...

  7. C++可视化和图表库

    目录 一.MathGL 二.Gnuplot 三.ChartDirector 四.Qt Charts 五.KD Chart 六.QWT 七.QCustomPlot 八.QtiPlot 九.C++和JS ...

  8. #visual studio# 运行库MT、MTd、MD、MDd

    在开发window程序是经常会遇到编译好好的程序拿到另一台机器上面无法运行的情况,这一般是由于另一台机器上面没有安装相应的运行时库导致的,那么这个与编译选项MT.MTd.MD.MDd有什么关系呢?这是 ...

  9. windows平台下使用cmake构建静态lib库以及使用静态lib库gtest项目

    有些时候我们需要将部分代码编译成单独的一个库,然后在另一个项目中去使用这个库 大部分是linux环境下的指令,但是也差不是很多 记录一下构建的经过 目录 1.使用cmake构建及使用lib库 构建li ...

  10. 【学习cmake】cmake如何使用链接库 (link_directories, LINK_LIBRARIES, target_link_libraries,FIND_PACKAGE)实践篇2

    cmake中添加引用动态链接和静态链接库 ADD_EXECUTABLE(a.out ./main.cpp) TARGET_LINK_LIBRARIES(a.out /usr/lib/libeg.so) ...

最新文章

  1. R语言嵌套的ifelse语距:将一条If语句放在另一条If语句中,该语句作为嵌套的If else调用。If else语句允许我们根据表达式结果(TRUE或FALSE)打印不同的语句,执行不同的语句块
  2. 黄聪:基于Linq to edmx的实体数据模型(EDM)类名批量修改工具
  3. 2021暑假实习-SSM超市积分管理系统-day09笔记
  4. LSSS线性秘密共享方案详细构造方法与原理解释试读
  5. 树莓派环境处理_一种基于树莓派的便携式的环境监测系统的制作方法
  6. 如何使用SQL Server数据工具中的“可见性”选项降低报告的复杂性
  7. wend计算机语言,计算机脚本语言开机显示当前页面发生
  8. 浅谈个人对项目管理的理解
  9. 24个基本指标精粹讲解(22)--ADR
  10. 我的理想600字作文计算机方面,我的理想作文600字当一名老师(共8篇)
  11. 武汉大学 gps 计算机 陈冰,武汉大学2015届优秀毕业研究生名单.doc
  12. 20个你应该知道的iPhone 7实用小技巧
  13. 二层交换机,三层交换机,四层交换机的区别
  14. matlab的汉明窗函数如何导出,基于汉明窗函数的FIR低通滤波器的设计.doc
  15. 瑞芯微RK3328芯片怎么样?RK3328处理器参数介绍
  16. 面试知识点——(金三银四你需要的是她)
  17. 基于STM32F103RB的模拟液位检测告警系统(已实现)
  18. html页面增加分页符
  19. mysql只允许指定ip网段_MySQL允许某个IP网段从远程访问的方法
  20. Java/HTML/CSS/JavaScript/Jsp实现的药店管理系统源码

热门文章

  1. 数据结构与算法之排序
  2. led伏安特性实验误差分析_为什么非线性电阻元件伏安特性曲线的误差分析?
  3. 桌面上计算机快捷方式打不开,桌面快捷方式打不开解决步骤
  4. 字节跳动Java工资待遇等级_字节跳动面试题:你的平均薪水是多少?
  5. 鸭子类型 Duck typing
  6. 通过SQL SERVER添加系统管理员帐号
  7. 独自一人开发返利平台小程序日记(准备开源中):万事开头难,既然做了,那就只能咬牙坚持了
  8. 2015最新移动App设计尺寸视觉规范【图文版】(转)
  9. 数字转换英语c语言程序,C语言编写的英语数字转化代码(数字转化为用英语表达的数字).doc...
  10. 叉乘点乘混合运算公式_数学公式总结人教版初一上册