cURL是项目的名称。该名称是“ URL的客户端”上的一个名称,最初是用大写的URL拼写的,以使其明显地处理URL
cURL项目产生两种产品:
libcurl
一个免费且易于使用的客户端URL传输库,支持DICT,FILE,FTP,FTPS,GOPHER,HTTP,HTTPS,IMAP,IMAPS,LDAP,LDAPS,MQTT,POP3,POP3S,RTMP,RTMPS,RTSP, SCP,SFTP,SMB,SMBS,SMTP,SMTPS,TELNET和TFTP。
curl
使用URL语法获取或发送文件的命令行工具
DICT
FILE
FTP
FTPS
GOPHER
GOPHERS
HTTP
HTTPS
IMAP
IMAPS
LDAP
LDAPS
MQTT
POP3
POP3S
RTMP
RTSP
SCP
SFTP
SMB
SMTP
SMTPS
TELNET(远程登陆)
TFTP
下载:
https://curl.se/download.html, 找到合适的版本
然后解压缩
‘curl’ is not recognized as an internal or external command
解决:
然后把解压的路径C:\Users\oceanstar\software\curl-7.75.0-win64-mingw\bin放在system environment中的PATH中
# wget https://curl.haxx.se/download/ curl-7.75.0.tar.gz
tar -xvf curl-7.75.0.tar.gz
cd curl-7.75.0/
./configure
make
make test (optional)
sudo make install
注意: ./configure 报错
error: no acceptable C compiler found in $PATH
说明没有安装GCC:
yum -y install gcc
3.命令测试
测试curl命令是否可用
# curl
curl: try 'curl --help' or 'curl --manual' for more information
若curl命令不可用,则通过shell指定命令的位置(此处已经知道命令被安装到/usr/local/bin位置)
export PATH=$PATH:/usr/local/bin
4.库、头文件和命令的安装位置
# 已安装的libcurl版本是什么
$ curl-config --version
libcurl 7.75.0
$ curl-config --cflags
-I/usr/local/include
$ curl-config --libs
-L/usr/local/lib -lcurl
$ ls /usr/local/include/
curl
ls /usr/local/lib
libcurl.so.4 libcurl.so.4.7.0 libcurl.a libcurl.la libcurl.so pkgconfig
1、CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(libcuul_study)
set(CMAKE_CXX_STANDARD 11)
include_directories(/usr/local/include)
link_directories(/usr/local/lib)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} curl)
2、main.cpp
#include
int main() {
CURL *curl = curl_easy_init();
if(curl) {
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, "https://www.baidu.com");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return 0;
}
easy界面是一个同步,搞笑,快速使用的用于文件传输的简单界面
概述
多重界面提供了简易界面所没有的几种功能。它们主要是:
libcurl
获取/发送数据如何使用
curl_multi_add_handle
将简易句柄添加到多句柄中,而不是使用curl_easy_perform
。您可以随时在多句柄中添加更多简单的句柄,即使其他传输已在运行中也是如此。#include
CURLM * curl_multi_init(); 作用:
- 创建一个多句柄
描述:
- 此函数返回一个CURLM句柄,以用作其他多功能的输入
- 操作完成后,此init调用必须具有对curl_multi_cleanup的相应调用。
返回值:
- 如果此函数返回NULL,则出问题了,您将无法使用其他curl函数
#include
CURLMcode curl_multi_cleanup(CURLM * multi_handle) 作用:
- 关闭多会话
描述:
作用:
描述:
timeout_ms
已经过去。或者如果多句柄的未决内部超时的到期时间比timeout_ms
短,则将用较短的时间来确保合理的保持超时精度#include
CURLMcode curl_multi_add_handle(CURLM * multi_handle,CURL * easy_handle);
作用:
描述:
curl_multi_remove_handle
作用:
- 从多会话中删除一个简单的句柄
描述:
- 从multi_handler删除一个给定的easy_handler
- 从多个堆栈中删除了easy句柄后,再次在此easy句柄上调用curl_easy_perform是完全合法的。
- 在使用过程中删除易用的手柄是完全合法的,这将有效地停止涉及该易用手柄的正在进行的传输。所有其他简单的操作和转移将不受影响。
- 可以在传输过程中随时删除句柄,只是不要从任何libcurl回调函数中删除句柄
作用:
描述:
作用:
描述:
msgs_in_queue
指向的整数将包含调用此函数后剩余的消息数curl_easy_getinfo
:struct CURLMsg {
CURLMSG msg; /* 此消息的含义*/
CURL *easy_handle; /* 所涉及的句柄, 用于获取详细信息 */
union {
void *whatever; /* 特定于消息的数据 */
CURLcode result; /* 返回代码,用于传输*/
} data;
};
#include
CURLMcode curl_multi_setopt(CURLM * multi_handle, CURLMoption option, param);
作用:
#include
CURLMcode curl_multi_setopt(CURLM * handle,CURLMOPT_PIPELINING,long bitmask);
作用:
描述:
#include
CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_TOTAL_CONNECTIONS, long amount);
作用:
例子:
CURLM * m = curl_multi_init();
/*永远不要进行超过15个连接*/
curl_multi_setopt(m,CURLMOPT_MAX_TOTAL_CONNECTIONS,15L);
#include
CURLMcode curl_multi_setopt(CURLM * handle,CURLMOPT_MAXCONNECTS,long max);
作用:
描述:
例子:
CURLM * m = curl_multi_init();
/ *仅在高速缓存中保留10个连接* /
curl_multi_setopt(m,CURLMOPT_MAXCONNECTS,10L);
#include
CURLcode curl_global_init(long flags); 作用:
- 全局libcurl初始化
描述:
- 此函数设置libcurl所需的程序环境。可以将其视为库加载器的扩展
- 在程序调用libcurl中的任何其他函数之前,该函数必须在程序中至少被调用一次(程序是共享内存空间的所有代码)。它设置的环境在程序的生命周期中是恒定的,并且对于每个程序都是相同的,因此多次调用与一次调用具有相同的效果
- flags是一种位模式,它可以告诉libcurl确切的初始化功能,如下所述,通过对这些值进行“或”运算来设置所需的位。在正常操作中,您必须指定CURL_GLOBAL_ALL。除非您熟悉它并打算控制libcurl的内部操作,否则请不要使用任何其他值
- 此函数不是线程安全的
原型:
#include
CURL *curl_easy_init( ); 作用:
- 创建一个简单的句柄,用来启动一个libcurl会话
描述:
- 此函数必须是第一个要调用的函数,它返回一个curl简易句柄,您必须使用它作为easy界面中其他函数的输入。
- 操作完成后,此调用必须具有对
curl_easy_cleanup
的相应调用- 如果尚未调用curl_global_init,curl_easy_init会自动执行此操作。这在多线程情况下可能是致命的,因为curl_global_init不是线程安全的,并且由于没有相应的清理,可能会导致资源问题
- 强烈建议您自己正确调用
curl_global_init
来禁止这种自动行为。有关如何使用此功能的详细信息,请参见libcurl(3)中的全局环境要求的描述。返回值:
- 如果此函数返回NULL,则表示错误,您将无法使用其他curl函数。
原型:
#include
void curl_easy_cleanup(CURL * handle ) 作用:
- 销毁一个简单的句柄,结束一个libcurl会话
描述:
- 此函数必须是调用简单会话的最后一个函数
- 这可能会关闭此手柄使用过的所有连接,并且可能移植保持打开状态-除非在进行传输时将其连接到多手柄上。如果要传输更多文件,请不要调用此函数,重新使用句柄是libcurl取得良好性能的关键
- 有时,您可能会从curl_easy_cleanup(如果先前使用curl_easy_setopt为该句柄设置)中调用了进度回调或标头回调。就像libcurl决定关闭连接,而协议属于那种在断开连接之前需要命令/响应序列的协议。此类协议的示例是FTP,POP3和IMAP。
- 在调用此函数并返回后,对句柄的任何使用都是非法的。curl_easy_cleanup会杀死该句柄以及与此相关的所有内存!
- 在handle中传递NULL指针将使此函数立即返回而无需执行任何操作
返回值:
- 无
CURL *curl = curl_easy_init();
if(curl) {
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
原型:
#include
CURLcode curl_easy_perform(CURL *easy_handle); 作用:同步执行文件传输
描述:
- 在curl_easy_init和所有curl_easy_setopt调用完成后调用此函数,并按照选项中的说明执行传输。
- curl_easy_perform以阻塞方式执行整个请求,并在完成或失败时返回。有关非阻塞行为,请参见
curl_multi_perform
。- 您可以在使用相同的easy_handle的同时对curl_easy_perform进行任意数量的调用。如果您打算传输多个文件,甚至会被鼓励这样做。然后,libcurl将尝试在以后的传输中重新使用相同的连接,从而使操作更快,CPU占用更少并占用更少的网络资源。请注意,在调用之间必须使用
curl_easy_setopt
来设置以下curl_easy_perform的选项。- 您绝不能使用相同的easy_handle从两个位置同时调用此函数。让函数先返回,然后再调用它。如果要并行传输,则必须使用多个curl easy_handles。
返回值:
- CURLE_OK(0)表示一切正常,非零表示
定义时发生错误-请参见 libcurl-errors
- 如果使用curl_easy_setopt设置了
CURLOPT_ERRORBUFFER
,则返回非零值时,错误缓冲区中将出现可读的错误消息。
CURL *curl = curl_easy_init();
if(curl) {
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
原型:
#include
void curl_easy_reset(CURL * handle ); 作用:
- 重置libcurl会话句柄的所有选项
- 它不会更改句柄中保留的以下信息:实时连接,会话ID缓存,DNS缓存,cookie,共享或alt-svc缓存。
原型:
#include
CURL * curl_easy_duphandle(CURL * handle ); 作用:
- 克隆一个libcurl会话句柄,返回一个新的curl手柄,随后可以独立使用两个句柄,并且必须使用curl_easy_cleanup释放它们。
- 新句柄也指向之前用curl_easy_setopt设置的url,但是会清空所有先前设置的选项
- 新的句柄将不会继承任何状态信息,没有连接,没有SSL会话以及没有cookie。它也不会继承任何共享对象的状态或选项(就像CURLOPT_SHARE设置为NULL一样)
- 在多线程程序中,必须以同步方式调用此函数,克隆后可能不使用输入句柄。
返回值:
- 如果此函数返回NULL,则出了点问题,并且没有返回有效的句柄。
原型:
#include
CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter); 作用:
- 设置curl句柄的选项
描述:
- curl_easy_setopt告诉libcurl如何运行。通过设置适当的选项,应用程序可以更改libcurl的行为。
- 使用此函数调用设置的选项对于使用此句柄执行的所有即将进行的传输均有效。传输之间不会以任何方式重置这些选项,因此,如果要使用不同的选项进行后续传输,必须在传输之间进行更改。您可以使用
curl_easy_reset
将所有选项重置为内部默认值- 设置选项的顺序无关紧要。\
行为选项 | |
---|---|
CURLOPT_VERBOSE | 显示详细信息 |
CURLOPT_HEADER | 在正文输出中包含标题 |
CURLOPT_NOPROGRESS | 关闭进度条 |
CURLOPT_NOSIGNAL | 不要安装信号处理程序 |
CURLOPT_WILDCARDMATCH | 启用目录通配符传输 |
网络选项 | |
---|---|
CURLOPT_URL | 提供要在请求中使用的URL |
使用:
#include
CURLcode curl_easy_setopt(CURL * handle,CURLOPT_URL,char * URL); 作用:
- 设置目标网址
- 必须设置的唯一选项,否则将无法进行传输
使用:
#include
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_VERBOSE, long onoff); 作用:
- 启动/禁用详细模式。
描述:
- 将onoff参数设置为1,以使库在该句柄上显示很多有关其操作的详细信息。对于libcurl或其他协议调试和理解非常有用。
- 将onoff参数设置为0,关闭详细输出,默认设置为0。
- 详细信息将发送到
stderr
或使用CURLOPT_STDERR
设置的流- 要获取所有发送和接收的协议数据,请考虑使用
CURLOPT_DEBUGFUNCTION
。
#include
int main() {
CURL *curl = curl_easy_init();
if(curl) {
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, "https://www.baidu.com");
// 请libcurl向我们显示详细输出
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
// 执行请求
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return 0;
}
使用:
#include
CURLcode curl_easy_setopt(CURL * handle,CURLOPT_HEADER,long onoff); 作用:
- 将标头传递到数据流
描述:
- 将onoff参数设置为1,以要求libcurl在写回调(CURLOPT_WRITEFUNCTION)中包含标头。此选项与实际上具体标头或其他元数据(比如HTTP和FTP)的协议有关
- 当要求将标头传递给与正文相同的回调时,如果没有关于所使用协议的详细知识,就不可能再次正确地分离它们。
#include
int main() {
CURL *curl = curl_easy_init();
if(curl) {
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, "https://www.baidu.com");
curl_easy_setopt(curl, CURLOPT_HEADER, 1);
// 执行请求
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return 0;
}
#include
CURLcode curl_easy_setopt(CURL * handle,CURLOPT_NOPROGRESS,long onoff); 作用:
- 关闭进度条
描述:
- onoff=1时,它会通知库针对使用此handler完成的请求完全关闭进度条。它还将防止调用CURLOPT_XFERINFOFUNCTION或CURLOPT_PROGRESSFUNCTION
#include
int main() {
CURL *curl = curl_easy_init();
if(curl) {
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, "https://www.baidu.com");
//启用进度表
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
// 执行请求
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return 0;
}
作用:
描述:
作用:
#include
CURLcode curl_easy_setopt(CURL * handle,CURLOPT_PRIVATE,void * pointer);
作用:
描述:
传递一个void * 作为参数,指向与此handler相关联的数据。我们可以使用curl_easy_getinfo与CURLINFO_PRIVATE选项读取。libcurl本身永远不会对这些数据做任何事情
作用:
描述:
描述:
作用:
作用:
#include
CURLcode curl_easy_setopt(CURL * handle,CURLOPT_SHARE,CURLSH * share);
作用:
描述:
作用:
描述:
作用:
示例:
#include
#include
// 带有Alt-Svc支持的HTTP
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl){
// 在此文件中缓存替代项
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
// 限制使用替代版本的HTTP
curl_easy_setopt(curl, CURLOPT_ALTSVC_CTRL, (long)
CURLALTSVC_H1|CURLALTSVC_H2|CURLALTSVC_H3);
//执行请求,res将获得返回码
res = curl_easy_perform(curl);
// 检查错误
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
// 总是清理
curl_easy_cleanup(curl);
}
return 0;
}
作用:
作用: 获取上传速度
描述:
作用:
描述:
#include
#include
#include
#include
#define FILE_PATH "/home/oceanstar/CLionProjects/acl_redis.tar.gz"
#define UPLOAD_URL "file:///home/oceanstar/cutimage"
int main(int argc, char *argv[]) {
CURL *curl;
CURLcode res;
struct stat file_info;
curl_off_t speed_upload, total_time;
FILE *fd;
fd = fopen(FILE_PATH, "rb");
if (fd) {
return 1;
}
if (fstat(fileno(fd), &file_info) != 0) {
return 1;
}
curl = curl_easy_init();
if (curl) {
// 上传到这个地方
curl_easy_setopt(curl, CURLOPT_URL,
UPLOAD_URL);
// 告诉库将要上传数据
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
// 设置读取位置(在Windows上也需要使用READFUNCTION)
curl_easy_setopt(curl, CURLOPT_READDATA, fd);
// 并给出上传的大小(可选)
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
(curl_off_t) file_info.st_size);
// 启用冗长以便于跟踪
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}else{
//现在提取传输信息
curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD_T, &speed_upload);
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &total_time);
fprintf(stderr, "Speed: %" CURL_FORMAT_CURL_OFF_T " bytes/sec during %"
CURL_FORMAT_CURL_OFF_T ".%06ld seconds\n",
speed_upload,
(total_time / 1000000), (long)(total_time % 1000000));
}
}
fclose(fd);
return 0;
}
#include
#include
#include
#include
#define FTP_SERVER "ftp://127.0.0.1/home/oceanstar/CLionProjects/acl_redis.tar.gz" //"ftp://127.0.0.1/home/data/cutimage/file.txt"
#define LOCAL_NAME "/home/oceanstar/CLionProjects/libcuul_study/build/new_name.tar.gz"
struct FtpFile{
const char *filename;
FILE *stream;
};
static size_t my_fwrite(void *buffer, size_t size, size_t nmemb,
void *stream){
struct FtpFile *out = (struct FtpFile *)stream;
if(!out->stream){
// 打开文件用于写入
out->stream = fopen(out->filename, "wb");
if(!out->stream){
return -1; // 失败,无法打开文件写入
}
}
return fwrite(buffer, size, nmemb, out->stream);
}
int main(int argc, char *argv[]) {
CURL *curl;
CURLcode res;
struct FtpFile ftpfile = {
LOCAL_NAME,
NULL
};
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl){
curl_easy_setopt(curl, CURLOPT_URL, FTP_SERVER);
// 定义我们的回调函数,以便在有数据要写入时被调用
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
//设置指向我们的结构的指针以传递给回调
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
//激活SSL,并且需要它同时用于控制和数据
//curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
// 打开完整的协议/调试输出
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
if(CURLE_OK != res) {
/* we failed */
fprintf(stderr, "curl told us %d\n", res);
}
}
if(ftpfile.stream)
fclose(ftpfile.stream); /* close the local file */
curl_global_cleanup();
return 0;
}
#include
#include
#include
#define FTP_SERVER "ftp://127.0.0.1/home/oceanstar/CLionProjects/acl_redis.tar.gz"
static size_t throw_away(void *ptr, size_t size, size_t nmemb, void *data)
{
(void)ptr;
(void)data;
/* we are not interested in the headers itself,
so we only return the size we would have saved ... */
return (size_t)(size * nmemb);
}
int main(int argc, char *argv[]) {
char ftpurl[] = FTP_SERVER;
CURL *curl;
CURLcode res;
long filetime = -1;
double filesize = 0.0;
const char *filename = strrchr(ftpurl, '/') + 1;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl){
curl_easy_setopt(curl, CURLOPT_URL, ftpurl);
//
curl_easy_setopt(curl, CURLOPT_NOBODY, 1l);
//询问文件时间
curl_easy_setopt(curl, CURLOPT_FILETIME, 1L);
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, throw_away);
curl_easy_setopt(curl, CURLOPT_HEADER, 0L);
//打开完整的协议/调试输出
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
if(CURLE_OK == res) {
res = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
if((CURLE_OK == res) && (filetime >= 0)) {
time_t file_time = (time_t)filetime;
printf("创建时间 %s: %s", filename, ctime(&file_time));
}
res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD,
&filesize);
if((CURLE_OK == res) && (filesize>0.0))
printf("文件大小 %s: %0.0f bytes\n", filename, filesize);
}else {
fprintf(stderr, "curl told us %d\n", res);
}
curl_easy_cleanup(curl);
}
return 0;
}
#include
#include
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/");
res = curl_easy_perform(curl);
if(CURLE_OK == res) {
char *ct;
/* ask for the content-type */
res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
if((CURLE_OK == res) && ct)
printf("We received Content-Type: %s\n", ct);
}
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
#include
#include
#include
int main()
{
char temp[2000];
struct curl_slist *headerlist=NULL;
CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "ftp://admin:[email protected]");
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
//下面3行是针对ssl
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
snprintf(temp, sizeof(temp), "MKD FTP_DIR");/* 执行的命令 创建FTP_DIR目录 */
headerlist = curl_slist_append(headerlist, temp);
curl_easy_setopt(curl, CURLOPT_QUOTE, headerlist);/* CURLOPT_QUOTE 对应的是命令行选项*/
CURLcode res = curl_easy_perform(curl);
curl_slist_free_all (headerlist);
curl_global_cleanup();
if(res == CURLE_OK) std::cout << "mkdir succ\n";
else std::cout << "mkdir fail " << res << std::endl;
}
#include
#include
#include
int main(int argc, char *argv[]) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl){
curl_easy_setopt(curl, CURLOPT_URL, "ftps://dss:[email protected]" );
// curl_easy_setopt(curl, CURLOPT_URL, "ftps://192.113.115.28" );
// curl_easy_setopt(curl, CURLOPT_USERPWD, "dss:admin12345");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
res = curl_easy_perform(curl);
if(CURLE_OK == res) {
printf("-----ok");
}else {
fprintf(stderr, "-------curl told us %d\n", res);
}
curl_easy_cleanup(curl);
}
return 0;
}
官网
参考: https://blog.csdn.net/u012234115/article/details/83869486