C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++ LibCurl库使用

C++中LibCurl库使用流程及配置详解

作者:ymjy121

libcurl是一个跨平台的开源网络传输库,它支持许多协议,包括HTTP、HTTPS、FTP、FTPS以及许多其他协议和文件传输方式,本文给大家详细介绍了C++中LibCurl库使用流程及配置,需要的朋友可以参考下

LibCurl库使用介绍

libcurl是一个跨平台的开源网络传输库,它支持许多协议,包括HTTP、HTTPS、FTP、FTPS、SCP、SFTP、TFTP、LDAP、以及许多其他协议和文件传输方式。libcurl允许开发者使用C语言编写代码来进行网络通信,并提供了简单易用的API接口。
libcurl的主要特点包括:

跨平台性: 可以在各种操作系统上使用,包括Linux、Windows、macOS等。多协议支持: 支持多种常用的网络协议,例如HTTP、FTP等,以及安全协议如HTTPS、FTPS等。功能丰富: 提供了丰富的功能和选项,可以用于各种网络传输需求,如文件上传、下载、POST请求等。高度可定制性: 提供了大量的选项和回调函数,使开发者能够定制和控制网络通信的细节。易用性: libcurl的API设计简单直观,容易上手,同时也提供了丰富的文档和示例。
由于其强大的功能和易用性,libcurl被广泛应用于各种软件和项目中,包括网络爬虫、下载工具、Web服务等。

libcurl使用基本流程

		
CURLcode curl_global_init(long flags); //这个函数只能用一次。(调用curl_global_cleanup清理后可再次使用初始化)
//参数:flags
 	//CURL_GLOBAL_ALL: 初始化所有的 libcurl 功能。
 	//CURL_GLOBAL_SSL: 初始化 SSL 相关的功能,如支持 HTTPS 议。
 	//CURL_GLOBAL_WIN32: 在 Windows 平台上初始化一些特定的功能。
 	//CURL_GLOBAL_NOTHING: 不做任何初始化,这种情况下需要手动初始化特定的功能。
//返回值: CURLcode 类型的错误码,如果初始化成功则返回 CURLE_OK,否则返回其他错误码表示初始化失败

curl_easy_setopt(curl, CURLOPT_URL, url.data());   // 设置要下载的URL地址
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);   // 设置回调函数以将数据写入文件
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &downloadData);   // 传递包含输出文件指针、进度等的结构体给回调函数

curl_easy_setopt() 函数详解:

CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
	//参数:
	//	- handle: 指向 CURL 句柄的指针,表示要设置选项的 CURL 句柄。
	//	- option: 枚举类型 CURLoption,表示要设置的选项类型。
	//	- parameter: 选项对应的参数值,类型根据不同选项而定,既可以是个函数的指针,也可以是某个对象的指针,也可以是个long型的变量
	常见CURLoption类型(更多CURLoption类型的选项都在curl.h库里有定义,man 也可以查看到):
		CURLOPT_URL: 设置请求的 URL。
		CURLOPT_HTTPHEADER: 设置请求头信息。
		CURLOPT_POSTFIELDS: 设置请求体数据。
		CURLOPT_TIMEOUT: 设置请求超时时间。
		CURLOPT_WRITEFUNCTION: 设置写数据回调函数。
		CURLOPT_WRITEDATA: 设置写数据回调函数的用户数据。
		CURLOPT_PROXY: 设置代理服务器地址。
		CURLOPT_SSL_VERIFYPEER: 设置是否验证对等证书。
		CURLOPT_SSL_VERIFYHOST: 设置是否验证主机名。
		CURLOPT_CUSTOMREQUEST: 设置自定义请求方法。
		CURLOPT_USERAGENT: 设置用户代理信息。
		CURLOPT_VERBOSE: 设置是否输出详细的调试信息。
		CURLOPT_FOLLOWLOCATION: 设置是否跟随重定向。
		CURLOPT_COOKIE: 设置请求中的 Cookie。
		CURLOPT_COOKIEFILE: 设置从文件中读取 Cookie。
		CURLOPT_COOKIEJAR: 设置保存 Cookie 到文件。
		CURLOPT_RESUME_FROM: 设置断点续传的起始位置。
		CURLOPT_LOW_SPEED_LIMIT: 设置低速下载速度限制。
		CURLOPT_LOW_SPEED_TIME: 设置低速下载持续时间。
		CURLOPT_CONNECTTIMEOUT: 设置连接超时时间
	
	例如:
	struct curl_slist *headers = NULL;
	headers = curl_slist_append(headers, "Content-Type: application/json");
	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);	//设置请求头
	curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");	//设置 URL
	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "key1=value1&key2=value2");	//设置请求体
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); // 设置请求超时时间,超时时间为10秒
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);//设置写数据回调函数
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);//设置回调函数用户数据
	curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.example.com:8080");	//设置代理
	curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //设置 SSL 选项, 禁止验证对等证书

部分枚举类型选项对应参数值说明

CURLOPT_WRITEFUNCTION 和 CURLOPT_WRITEDATA: 是配合使用的选项,用于设置写数据回调函数和回调函数的用户数据。

size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);
//参数:
	- ptr 是接收到的数据缓冲区指针,
	- size 是单个数据块的大小,
	- nmemb 是数据块的数量,
	- userdata 是传递给 CURLOPT_WRITEDATA 的用户数据指针。
//返回值:回调函数返回接收到的数据大小。
int progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
//参数:
	- clientp 是传递给 `CURLOPT_PROGRESSDATA` 的用户数据指针,
	- dltotal 是预期下载总字节数,
	- dlnow 是当前已下载字节数,
	- ultotal 是预期上传总字节数,
	- ulnow 是当前已上传字节数。
//返回值:回调函数应该返回 0 以继续下载操作,返回非零值表示终止下载操作。
      • CURLOPT_PROGRESSDATA:设置用户数据指针
    • CURLOPT_TIMEOUT,`CURLOPT_CONNECTIONTIMEOUT,用于设置超时时间
      • CURLOPT_TIMEOUT:设置请求的总超时时间,即从发送请求到接收完整响应的总时间。如果在指定的时间内未完成请求,libcurl 将会放弃请求,并返回超时错误。该选项的参数是一个长整型值,表示超时时间的秒数;用于对完整响应时间比较关注的场景,例如下载文件、访问网页等。
      • CURLOPT_CONNECTTIMEOUT:该选项用于设置连接超时时间,即建立连接的时间。如果在指定的时间内未能建立连接,libcurl 将会放弃连接尝试,并返回连接超时错误。该选项的参数也是一个长整型值,表示超时时间的秒数;适用于对连接建立时间比较关注的场景,例如需要快速响应的短连接请求
    • CURLOPT_RANGE 和 CURLOPT_RESUME_FROM 是 libcurl 中用于实现断点续传
      • CURLOPT_RANGE:设置 HTTP 请求的范围,即指定需要下载的文件的范围。它的参数是一个字符串,格式为 start-end,表示从文件的 start 字节处开始下载,直到 end 字节结束。如果 end 留空,则表示下载从 start 字节开始到文件末尾。用于指定下载文件的范围,允许下载文件的任意部分内容,不仅仅限于断点续传。
      • CURLOPT_RESUME_FROM:该选项用于设置断点续传的起始位置,即指定从文件的哪个字节处开始继续下载。它的参数是一个长整型值,表示断点续传的起始字节位置,主要用于实现断点续传,指定从文件的指定位置开始继续下载
    • CURLOPT_VERBOSE是 libcurl 中的一个选项,选项值类型:long,用于控制是否打印详细的调试信息。设置为非零值时,libcurl 将打印出大量的调试信息,包括请求和响应的头部、数据传输的详细信息等。这些信息对于调试和排查问题非常有用,但在正常情况下可能会显得冗长。通常不会将 CURLOPT_VERBOSE 设置为非零值,因为打印大量的调试信息会影响程序的性能并增加日志的大小。但在调试和开发阶段,可以将其设置为非零值来帮助排查问题。
  1. 执行请求CURLcode res = curl_easy_perform(curl); //执行HTTP请求

  2. 处理响应: 根据请求的结果进行相应的处理,如处理响应数据、错误处理等。

if (res != CURLE_OK) {
    fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
} else {    // 请求成功,处理响应数据  }

//以下是一些常用的 CURLcode 枚举值,详细的错误描述字符串,可以通过const char *curl_easy_strerror(CURLcode errornum ) 这个函数取得
CURLE_OK (0): 操作成功完成。
CURLE_UNSUPPORTED_PROTOCOL (1): 不支持的协议。
CURLE_URL_MALFORMAT (3): URL 格式错误。
CURLE_COULDNT_RESOLVE_HOST (6): 无法解析主机名。
CURLE_COULDNT_CONNECT (7): 无法连接到主机或代理。
CURLE_OPERATION_TIMEDOUT (28): 操作超时。
CURLE_SSL_CONNECT_ERROR (35): SSL/TLS 连接错误。
CURLE_PEER_FAILED_VERIFICATION (51): 对等证书验证失败。
CURLE_GOT_NOTHING (52): 未收到任何数据。
CURLE_SEND_ERROR (55): 发送数据时出错。
CURLE_RECV_ERROR (56): 接收数据时出错。
CURLE_SSL_CERTPROBLEM (58): 证书问题。
CURLE_SSL_CIPHER (59): SSL/TLS 密码错误。
CURLE_SSL_CACERT (60): 未找到合适的 CA 证书。
CURLE_USE_SSL_FAILED (64): 使用 SSL/TLS 失败。

代码示例:

#include <stdio.h>
#include <curl/curl.h>


struct DownloadData {
	FILE *file = nullptr; // 声明为 null ;
	s32 fileSize;
	s32 downloaded;
	std::string hash;
	bool isInitialized = false;
};

// 定义写数据回调函数
size_t HttpDownloadService::WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) {
	// size_t data_size = size * nmemb; // 计算本次写入的数据总大小(size是单个数据块大小,nmemb是块的数量)
   	// 获取传递进来的DownloadData结构体指针
   	struct DownloadData *downloadData = (struct DownloadData *) userp;
   // 将数据块写入文件,返回实际写入的大小
    size_t write_size = fwrite(contents, size, nmemb, downloadData->file);
  	downloadData->downloaded += write_size;  // 更新已下载的总字节数
   	if (downloadData->fileSize > 0) {
     	downloaded = downloadData->downloaded;
        double progress = (double) downloadData->downloaded / downloadData->fileSize * 100; 
        std::cout << " Download fileSize: " << downloadData->fileSize << "  Download Progress: " << progress << "%" << std::endl;
      }
   	return write_size;
}
        
int main() {
      curl_global_init(CURL_GLOBAL_ALL);// 初始化CURL库
      CURL *curl = curl_easy_init();  // 获取一个CURL句柄用于本次传输    
      if (curl) {      
     	const char *outputFileName = "aaa.txt";
        struct DownloadData downloadData;
        // 以二进制写模式打开输出文件
        downloadData.file = fopen(outputFileName, "wb"); // Open the file and get FILE* pointer
        downloadData.fileSize = 7022;  // 预期的总文件大小,字节数
        downloadData.downloaded = 0;    // 已下载的字节数
        downloadData.hash = "8b32dbbdfcffc01ae7ff4cd29c9e4bfa973e9df29a629c80605d374d4237e2ba"; // 预期的下载文件SHA256哈希值
        
        curl_easy_setopt(curl, CURLOPT_URL, “http://example.com”);   // 设置要下载的URL地址
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);   // 设置回调函数以将数据写入文件
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &downloadData);   // 传递包含输出文件指针、进度等的结构体给回调函数
        curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);   // 启用进度回调
        curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, nullptr);  // 进度回调函数可选,这里不使用
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);

      		CURLcode res = curl_easy_perform(curl);  // 执行请求
        if (res != CURLE_OK) {
        	// 请求失败,处理错误
             std::cout << "Download failed: {}: " << curl_easy_strerror(res)<< std::endl;
        } else {
         	// 请求成功,处理响应数据
            logger->Info(SRC_LOC, "Download completed successfully.");
            std::cout << "Download completed successfully. " << std::endl;
            //……eg:对比文件大小和hash检查下载文件是否正常
        }

        curl_easy_cleanup(curl);    // 清理CURL句柄资源
        fclose(downloadData.file); // Close the file
      }
       
    curl_global_cleanup();  // 清理CURL库资源
    return 0;
}
		

以上就是C++中LibCurl库使用流程及配置详解的详细内容,更多关于C++ LibCurl库使用的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文