文章目录
前言
Curl是一个开源的命令行工具和库,用于进行网络数据传输。它支持多种协议,包括HTTP、FTP、SMTP、POP3等。Curl可以用来发送HTTP请求、下载文件、上传文件、进行文件传输等。
一、curl的特点
- 多协议支持:Curl支持多种网络协议,包括HTTP、HTTPS、FTP、SMTP、POP3等。
- SSL支持:Curl支持通过HTTPS进行安全的数据传输,并且可以验证服务器的证书。
- 代理支持:Curl可以通过代理服务器发送请求,支持HTTP、HTTPS、FTP等代理。
- 断点续传:Curl支持断点续传,可以在下载文件时恢复中断的传输。
- Cookie支持:Curl可以自动处理和发送Cookie,方便进行用户认证和会话管理。
- 数据上传:Curl可以用来上传文件,支持多种文件传输协议。 自定义请求:Curl提供了丰富的选项,可以自定义请求头、请求方法、请求体等。
二、交叉编译
1.前期准备工作
- 下载curl 点击这里去下载
- 解压缩curl
unzip curl-8.2.1.zip
- 查询cmake版本
curl需要至少3.7.0版本的cmake,root@ubuntu:/# cmake --version cmake version 3.5.1 CMake suite maintained and supported by Kitware (kitware.com/cmake).
2.手动更新cmake版本(cmake版本不小于3.7.0的可以看下一步)
- 点击这里 去下载
- 我下载的是3.7版本的cmake cmake-3.7.0-Linux-x86_64.tar.gz
- 解压缩:
tar -zxvf cmake-3.7.0-Linux-x86_64.tar.gz
- 备份之前的cmake
mv /usr/bin/cmake /usr/bin/cmake_3.5.1.bak
- 替换新的cmake(需要复制cmake到share路径下)
cd cmake-3.7.0-Linux-x86_64 cp bin/cmake /usr/bin cp share/cmake-3.7 /usr/share -rf
- 查询cmake版本
root@ubuntu:/# cmake --version cmake version 3.7.0 CMake suite maintained and supported by Kitware (kitware.com/cmake).
3.交叉编译curl
-
./configure --host=arm-linux-gnueabihf --prefix=/home/curl-8.2.1/bin -without-ssl
- –host指定的是交叉编译工具链的前缀,需要全局可以搜索到
- –prefix 指定make install时的安装路径
- -without-ssl 禁用ssl(会无法使用https) 我不需要就禁用了 如果要用需要交叉编译ssl,后续用到了我会再出一篇教程
- 执行完成后会有使能了模块的打印说明
- 可以看到 https后面的no,说明没有使能.
- http1后面的enabled 说明使能了
configure: Configured to build curl/libcurl: Host setup: arm-unknown-linux-gnueabihf Install prefix: /home/curl-8.2.1/bin Compiler: arm-linux-gnueabihf-gcc CFLAGS: -Werror-implicit-function-declaration -O2 -Wno-system-headers -pthread CPPFLAGS: LDFLAGS: LIBS: curl version: 8.2.1 SSL: no (--with-{openssl,gnutls,nss,mbedtls,wolfssl,schannel,secure-transport,amissl,bearssl,rustls} ) SSH: no (--with-{libssh,libssh2}) zlib: no (--with-zlib) brotli: no (--with-brotli) zstd: no (--with-zstd) GSS-API: no (--with-gssapi) GSASL: no (libgsasl not found) TLS-SRP: no (--enable-tls-srp) resolver: POSIX threaded IPv6: enabled Unix sockets: enabled IDN: no (--with-{libidn2,winidn}) Build libcurl: Shared=yes, Static=yes Built-in manual: enabled --libcurl option: enabled (--disable-libcurl-option) Verbose errors: enabled (--disable-verbose) Code coverage: disabled SSPI: no (--enable-sspi) ca cert bundle: no ca cert path: ca fallback: LDAP: no (--enable-ldap / --with-ldap-lib / --with-lber-lib) LDAPS: no (--enable-ldaps) RTSP: enabled RTMP: no (--with-librtmp) PSL: no (libpsl not found) Alt-svc: enabled (--disable-alt-svc) Headers API: enabled (--disable-headers-api) HSTS: no (--enable-hsts) HTTP1: enabled (internal) HTTP2: no (--with-nghttp2, --with-hyper) HTTP3: no (--with-ngtcp2 --with-nghttp3, --with-quiche, --with-msh3) ECH: no (--enable-ech) WebSockets: no (--enable-websockets) Protocols: DICT FILE FTP GOPHER HTTP IMAP MQTT POP3 RTSP SMTP TELNET TFTP Features: AsynchDNS IPv6 Largefile UnixSockets alt-svc threadsafe
- –host指定的是交叉编译工具链的前缀,需要全局可以搜索到
-
make
-
make install
- 完成后可以去**–prefix**指定的目录下去查看 生成的文件
bin/curl
是可以在该平台执行的工具lib/libcurl*
是静态与动态链接库,配合include文件夹下面的头文件可以编译到c/c++程序中
三、在c++中使用并下载文件,同时打印下载百分比
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "curl/curl.h"
struct CurlProgressData
{
double last_progress;
double* para_in_progress;
FILE* fp;
};
/*私有函数 写文件*/
size_t scurl_write_file(void* ptr, size_t size, size_t nmemb, FILE* stream)
{
return fwrite(ptr, size, nmemb, stream);
}
/*私有函数 进度回调函数*/
int scurl_progress_callback(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
struct CurlProgressData* progress = (struct CurlProgressData*)clientp;
if (dltotal > 0)
{
double current_progress = (double)dlnow / (double)dltotal * 100.0;
if ((current_progress - progress->last_progress >= 1.0) || (current_progress == 100.0))
{
printf("Download Progress: %.2f%%\n", current_progress);
progress->last_progress = current_progress;
if (progress->para_in_progress)
{
*progress->para_in_progress = current_progress;
}
}
}
return 0;
}
/**
***************************************************************************
函 数 名 : curlDownloadFileProgress
功能描述 : 去url地址下载文件并保存为saveName,同时记录下载进度,保留小数点后两位
输入参数 : const char* url url地址 完整的 例:http://xxx.com/xxx/xx.zip
const char* saveName 保存的文件名称,需要是全路径 例:/tmp/load.zip
double* process 进度
返 回 值 : bool true:下载成功 false:下载失败
修改历史 :
日 期 : 2023年8月18日
作 者 : xzf
修改内容 : 新生成函数
*****************************************************************************/
bool curlDownloadFileProgress(const char* url, const char* saveName, double* process)
{
CURL* curl;
FILE* fp;
CURLcode res;
bool ret = false;
struct CurlProgressData progress = {0.0, NULL, NULL};
progress.para_in_progress = process;
H_LOG_DEBUG(" url[%s]", url);
H_LOG_DEBUG("saveName[%s]", saveName);
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (!curl)
{
H_LOG_ERROR("curl_easy_init() failed");
return ret;
}
curl_easy_setopt(curl, CURLOPT_URL, url);
// 打开文件用于保存下载的内容
fp = fopen(saveName, "wb");
if (fp)
{
// 设置写入数据的回调函数和文件指针
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, scurl_write_file);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
// 设置进度回调函数和进度数据指针
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, scurl_progress_callback);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &progress);
// 执行下载操作
res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
H_LOG_ERROR("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
else
{
*progress.para_in_progress = 100.0;
ret = true;
}
// 关闭文件
fclose(fp);
}
else
{
H_LOG_ERROR("fopen(%s) failed", saveName);
}
curl_easy_cleanup(curl);
curl_global_cleanup();
return ret;
}
void main()
{
double upgrade_plan = 0;
bool ret = curlDownloadFileProgress("http://123/api/version/Get","/tmp/upgrade.zip",&upgrade_plan);
}
四、在c++中使用并执行get方法获取返回内容
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "curl/curl.h"
/*私有函数 写缓冲器*/
size_t scurl_write_buffer(void* ptr, size_t size, size_t nmemb, void* userdata)
{
size_t totalSize = size * nmemb;
char** buffer = (char**)userdata;
// 计算当前缓冲区的大小
size_t currentSize = 0;
if (*buffer)
{
currentSize = strlen(*buffer);
}
// 分配新的缓冲区,并将数据追加到缓冲区中
char* newBuffer = (char*)realloc(*buffer, currentSize + totalSize + 1);
if (newBuffer)
{
memcpy(newBuffer + currentSize, ptr, totalSize);
newBuffer[currentSize + totalSize] = '\0';
*buffer = newBuffer;
}
return totalSize;
}
/*****************************************************************************
函 数 名 : curlGetUrlTobuf
功能描述 : 执行get命令 可选择携带参数,相应内容放在para中
输入参数 : const char* url url地址 例:http://xx.xx.com
const char* para 携带的参数注意格式?A=B&C=D
char** response 响应的内容,传递进来的需要为NULL,使用完成后需要手动free释放
返 回 值 : bool true:请求成功 false:请求失败
修改历史 :
日 期 : 2023年8月18日
作 者 : xzf
修改内容 : 新生成函数
*****************************************************************************/
bool curlGetUrl(const char* url, const char* para, char** response)
{
CURL* curl;
CURLcode res;
bool ret = false;
H_LOG_DEBUG("url[%s]", url);
if (para)
{
H_LOG_DEBUG("para[%s]", para);
}
char* resp_buffer = *response;
if (*response)
{
H_LOG_ERROR("response != nullptr");
free(*response);
*response = nullptr;
H_LOG_ERROR("reset response success");
}
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (!curl)
{
H_LOG_ERROR("curl_easy_init() failed");
return ret;
}
// 设置基本的URL
curl_easy_setopt(curl, CURLOPT_URL, url);
if (para)
{
// 获取当前的URL
char* url;
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
// 拼接参数到URL上
char full_url[256];
sprintf(full_url, "%s%s", url, para);
curl_easy_setopt(curl, CURLOPT_URL, full_url);
}
// 创建缓冲区,并将其传递给写入回调函数
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, scurl_write_buffer);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp_buffer);
// 执行GET请求
res = curl_easy_perform(curl);
// 检查请求是否成功
if (res != CURLE_OK)
{
H_LOG_ERROR("请求失败:%s\n", curl_easy_strerror(res));
if (resp_buffer)
{
free(resp_buffer);
resp_buffer = nullptr;
}
}
else
{
ret = true;
// 打印存储的数据
*response = resp_buffer;
H_LOG_DEBUG("收到的数据:[%s]", *response);
}
curl_easy_cleanup(curl);
curl_global_cleanup();
return ret;
}
void main()
{
char* response = NULL;
bool ret = curlGetUrl("http://123/api/version/Get","?A=B&C=D",&response );
if(ret)
{
//...
free(response);
}
}
五、简单的curl工具使用,很简单
# 下载一个图片(get方法)
./curl http://www.aaa.bbb.com/get/img.jpg
总结
好了,关于curl工具的分享就到这里了,大家有什么问题欢迎评论,我看到了会第一时间回复