Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

C++封装libcurl, 实现的http客户端, 支持http(s)请求, 支持下载文件(断点续传和分片下载)

License

Notifications You must be signed in to change notification settings

Leopard-C/iclient

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

11 Commits

Repository files navigation

iClient (iC Client)

【C++】基于libcurl的HTTP请求客户端。

  • C++版本:c++11
  • 支持WindowsLinux
  • 引入方法:#include "iclient/iclient.h"

1. 功能与特点

  • HTTP、POST、PUT、DELETE、HEAD请求
  • 是否重定向,及重定向最大次数
  • 超时(毫秒)
  • SSL证书和密钥
  • 验证HTTPS请求对象的合法性
  • HTTP(s)代理
  • 接受的内容编码方式 (Accept-Encoding)
  • Cookie
  • Post请求数据(可设置MIME类型)
  • 自定义传输进度处理(例如下载进度条)
  • 文件下载(普通下载、断点续传、分片下载)
  • 限制下载/上传速度

2. 关键命名空间与类

  • namespace ic:
    • namespace client:
      • namespace http
        • enum Method: GET/POST/HEAD/...
        • enum StatusCode: HTTP状态码
        • enum Version: V1_0/V1_1/V2_0/...
      • namespace util
      • enum Status: Request请求的状态码(如超时、DNS错误等)
      • struct ProxyData: 描述一个HTTP(s)代理的相关信息
      • class Request
      • class Response
      • class Executor: 真正执行Request请求
      • class Url: 封装URL对象,便于添加、合并参数

3. 编译构建

如果机器上没有安装libcurl,可以在 Release页面 下载。

release-v1.0.1

下载后,将静态库文件放在lib目录下,目录结构如下:

lib
├── linux
│  └── libcurl.a
└── windows
 ├── Win32
 │  ├── Debug
 │  │  └── libcurl.lib
 │  └── Release
 │  └── libcurl.lib
 └── x64
 ├── Debug
 │  └── libcurl.lib
 └── Release
 └── libcurl.lib
  • linux平台:
# 使用makefile
make iclient # 编译静态库文件 (lib/linux/x86_64/libiclient.a)
make example.out # 编译示例代码 (bin/example.out)
# 也可以使用xmake构建
xmake f -m release
xmake b iclient
xmake b example.out
  • windows平台:

使用Visual Studio 2019打开win-build/iclient.sln解决方案。

编译iclient项目生成静态库文件 (lib/windows/x64/Release/iclient.lib)

编译example项目生成示例程序 (bin/example.exe)

3. 简单使用

可以参考 example/目录下的文件

$ tree example
example
├── main.cpp
├── test_download.cpp
├── test_download_range.cpp
├── test_download_resume.cpp
├── test_download_speed_limit.cpp
├── test_http_get.cpp
├── test_http_post.cpp
├── test_http_put.cpp
└── test_url.cpp

3.1 ic::client::Url的使用

例如需要构造一个URL,https://api.icrystal.top/util/random?min=1&max=100&count=20,该链接含有3个参数。

ic::client::Url url("https://api.icrystal.top/util/random");
url.SetParam("min", 1);
url.SetParam("max", 100);
url.SetParam("count", 20)
// 获取合并的参数串
// "min=1&max=100&count=20"
url.GetParamsString();
// 获取整个URL字符串
// "https://api.icrystal.top/random?min=1&max=100&count=20"
url.ToString();

注意 !

  • AddParam: 添加参数,保留同名的其他参数,如:
AddParam("name", "Tom"); "name=Tom"
AddParam("name", "Jack"); "name=Tom&name=Jack"
  • setParam: 唯一参数,覆盖同名的参数值。
SetParam("name", "Tom"); "name=Tom"
SetParam("name", "Jack"); "name=Jack"

3.2 GET/POST请求

GET请求

ic::client::Request request("http://httpbin.org/ip");
//request.set_http_method(ic::client::http::Method::HTTP_GET); // 默认为GET请求
ic::client::Response res = request.Perform();
if (res.status() == ic::client::Status::SUCCESS && 
 res.http_status_code() == ic::client::http::StatusCode::HTTP_200_OK) // 等价于 if (res.ok()) { ... }
{
	std::cout << res.data() << std::endl;
}

POST请求

ic::client::Request request("http://httpbin.org/ip");
request.set_http_method(ic::client::http::Method::HTTP_POST);

3.3 设置/获取header

Header名称不区分大小写!

// 设置Request的header
request.set_header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Ap...");
request.set_header("referer", "https://www.biaud.com");
auto res = request.Perform();
// 获取Response的header
// std::map<std::string, std::string>
auto& headers = res.headers();
for (auto& header : headers) {
 std::cout << header.first << ": " << header.second << std::endl;
}
res.HasHeader("Content-Length"); // true
res.GetHeader("Content-Length"); // 10134

3.4 设置代理

struct ProxyData {
 ProxyType type = ProxyType::HTTP;
 uint32_t port;
 HttpAuthType auth_type = HttpAuthType::ANY;
 std::string host;
 std::string username;
 std::string password;
};
ProxyData proxy_data;
proxy_data.host = "11.12.13.14";
proxy.data.port = 3011;
proxy.type = ic::client::ProxyType::HTTP;
request.set_proxy(proxy_data);
// 或者
request.set_proxy("11.12.13.14", 3011, ic::client::ProxyType::HTTP);

3.5 设置Cookie

request.set_cookie("name=Tom&age=18");
request.set_cookie_file("/etc/xxx/cookie/12345.cookie");

3.6 设置Post Data

request.set_data("{\"name\":\"Tom\"}");

3.7 重定向(次数)

request.set_max_redirects(3); // 最多重定向3次
request.set_max_redirects(0); // 设为0,表示禁止重定向
request.set_max_redirects(-1); // 设为-1,表示不限制重定向次数(默认)

3.8 HTTPS验证

request.set_verify_ssl_host(false);
request.set_verify_ssl_peer(false);
request.set_verify_ssl_status(false);
request.set_verify_ssl(false); // 等价于上面三条语句

3.9 下载文件

// @downloadFile: 下载的本地文件名
// @resume(bool): 是否启用断点续传,默认不启用
request.set_download_file("output.jpg"/*, false*/);
// @range: 单位bytes
// 包括0和4095
request.set_download_range(0, 4095);

3.10 设置传输进度回调函数

request.set_transfer_progress_handler(url_xfer_info_callback);

其中,url_xfer_info_callback 函数签名如下

 bool s_curl_xfer_info(
 const ic::client::Request& request,
 curl_off_t download_total_bytes, /* 总共需要下载的字节数 */
 curl_off_t download_now_bytes, /* 已经下载的字节数 */
 curl_off_t upload_total_bytes, /* 总共需要上传的字节数 */
 curl_off_t upload_now_bytes); /* 已经上传的字节数 */

3.11 更多设置项

可查看 include/iclient/request.h

4. example

No.5 断点续传

breakpoint_continue

No.6 分片下载(可以放到不同的线程中同时下载,即多线程下载)

download_range

5. 注意事项

如果使用libcurlopenssl的静态链接库,在多线程环境下发送HTTPS请求,需要在每个线程结束前调用OPENSSL_thread_stop()函数执行清理工作,否则可能产生内存泄露。

#include <openssl/crypto.h>
int main() {
 std::thread t([]{
 // send https request
 OPENSSL_thread_stop(); // call before thread exit
 });
 t.join();
 return 0;
}

ref: https://curl.se/libcurl/c/threadsafe.html

All current TLS libraries libcurl supports are thread-safe.

OpenSSL 1.1.0+ can be safely used in multi-threaded applications provided that support for the underlying OS threading API is built-in. For older versions of OpenSSL, the user must set mutex callbacks.

libcurl may not be able to fully clean up after multi-threaded OpenSSL depending on how OpenSSL was built and loaded as a library. It is possible in some rare circumstances a memory leak could occur unless you implement your own OpenSSL thread cleanup.

For example, on Windows if both libcurl and OpenSSL are linked statically to a DLL or application then OpenSSL may leak memory unless the DLL or application calls OPENSSL_thread_stop() before each thread terminates. If OpenSSL is built as a DLL then it does this cleanup automatically and there is no leak. If libcurl is built as a DLL and OpenSSL is linked statically to it then libcurl does this cleanup automatically and there is no leak (added in libcurl 8.8.0).

END

leopard.c@outlook.com

About

C++封装libcurl, 实现的http客户端, 支持http(s)请求, 支持下载文件(断点续传和分片下载)

Resources

License

Stars

Watchers

Forks

Packages

No packages published

AltStyle によって変換されたページ (->オリジナル) /