liunx - libcurl

1. 基本介绍

libcurl 是一个免费且易于使用的客户端 URL 传输库,支持 DICT、FILE、FTP、FTPS、GOPHER、GOPHERS、HTTPS、IMAP、IMAPS、LDAP、LDAPS、MQTT、POPP3、POP3S、RTMP、RTMPS、RTSP、SCP、SFTP、SMB、SMBS、SMTP、SMTPS、TELNET 和 TFTP。libcurl 支持 SSL 证书、HTTP POST、HTTP PUT、
FTP 上传、基于 HTTP 表单的上传、代理、HTTP/2、HTTP/3、cookie、用户+密码身份验证(基本、摘要、NTLM、协商、Kerberos)、文件传输恢复、http 代理隧道等等!

官网 : libcurl
curl版本 :curl-7.71.1.tar.gz 下载地址 https://curl.se/download/
openssl :openssl-1.1.1c.tar.gz 下载命令 wget https://www.openssl.org/source/openssl-1.1.1c.tar.gz

2. 安装

libcurl

  1. ./configure --prefix=$PWM/_install --with-ssl (perfix 填写路径 , withd-ssl 支持 ssl)
  2. make
  3. sudo make install
    只要没有error 且目录出现 _install 就表示安装成功 ,如果出现错误可能是 openssl 没有安装

openssl

  • ./config
  • make
  • sudo make install

3. 相关函数

  • curl_global_init() 初始化libcurl
  • curl_easy_init() 得到 easy interface型指针
  • curl_easy_cleanup() 释放内存
  • curl_easy_setopt() 设置的传输选项,实现回调函数以完成用户特定任务
  • curl_easy_perform() 函数进行访问请求

2.1 curl_global_init()

概要#include <curl/curl.h>CURLcode curl_global_init(long flags);描述此函数设置 libcurl 所需的程序环境。可以将其视为库加载程序的扩展。在程序调用libcurl中的任何其他函数之前,必须在程序中至少调用一次此函数(程序是共享内存空间的所有代码)。它设置的环境在程序的生命周期内是恒定的,并且对于每个程序都是相同的,因此多个调用与一个调用具有相同的效果。flags 选项是一种位模式,它准确地告诉 libcurl 要初始化哪些功能,如下所述。通过将值 OR 组合在一起来设置所需的位。在正常操作中,必须指定CURL_GLOBAL_ALL。不要使用任何其他值,除非你熟悉它并且意味着控制libcurl的内部操作。此函数是线程安全的,因为 libcurl 7.84.0 curl_version_info设置了CURL_VERSION_THREADSAFE功能位(大多数平台)。如果这不是线程安全的,则当程序中的任何其他线程(即共享同一内存的线程)正在运行时,不得调用此函数。这不仅仅意味着没有其他线程在使用 libcurl。由于curl_global_init调用其他库的函数,这些函数同样线程不安全,因此它可能与使用这些其他库的任何其他线程冲突。如果要从 Windows DLL 初始化 libcurl,则不应从 DllMain 或静态初始值设定项初始化它,因为 Windows 在此期间持有加载程序锁,并且可能会导致死锁。有关如何使用此函数的详细信息,请参阅 libcurl 中的全局环境要求说明。标志CURL_GLOBAL_ALL初始化一切可能。这将设置除 CURL_GLOBAL_ACK_EINTR 之外的所有已知位。CURL_GLOBAL_SSL(自 7.57.0 以来,此标志的存在或不存在没有任何意义。下面的描述适用于较旧的 libcurl 版本。初始化 SSL。这里的含义是,如果未设置此位,则SSL层的初始化需要由应用程序完成,或者至少在libcurl之外完成。如何进行SSL初始化的确切过程取决于libcurl使用的TLS后端。在没有初始化 TLS 层的情况下执行基于 TLS 的传输可能会导致意外行为。CURL_GLOBAL_WIN32初始化 Win32 套接字库。这里的含义是,如果未设置此位,则 winsock 的初始化必须由应用程序完成,否则可能会获得未定义的行为。当初始化在 libcurl 之外处理时,此选项存在,因此 libcurl 无需再次执行此操作。CURL_GLOBAL_NOTHING不初始化任何额外的内容。这不会设置位。CURL_GLOBAL_DEFAULT明智的默认值。它将同时初始化SSL和Win32。现在,这等于CURL_GLOBAL_ALL掩码的功能。CURL_GLOBAL_ACK_EINTR自 7.69.0 以来,此位没有意义,但其行为是默认值。在 7.69.0 之前:设置此标志时,curl 将在连接或等待数据时确认 EINTR 条件。否则,curl 会一直等到完全超时过去。(7.30.0 中新增)

2.2 curl_easy_init()

概要#include <curl/curl.h>CURL *curl_easy_init();描述此函数必须是要调用的第一个函数,它返回一个 CURL 简易句柄,您必须将该句柄用作简易界面中其他函数的输入。此调用必须具有相应的调用才能在操作完成时curl_easy_cleanup。如果您尚未呼叫curl_global_init,curl_easy_init会自动执行此操作。这在多线程情况下可能是致命的,因为curl_global_init不是线程安全的,并且由于没有相应的清理,它可能会导致资源问题。强烈建议您不要允许这种自动行为,请正确调用curl_global_init自己。参见 libcurl(3) 中关于全局环境需求的说明 来了解如何使用这个函数的细节。

2.3 curl_easy_cleanup()

概要#include <curl/curl.h>void curl_easy_cleanup(CURL *handle);描述此函数必须是调用简单会话的最后一个函数。它与 curl_easy_init 函数相反,必须使用与curl_easy_init调用返回的输入相同的句柄进行调用。这可能会关闭此句柄使用的所有连接,并且可能一直保持打开状态 - 除非它在执行传输时连接到多句柄。如果您打算传输更多文件,请不要调用此函数,重用句柄是使用 libcurl 获得良好性能的关键。有时,您可能会收到从curl_easy_cleanup中调用进度回调或标头回调(如果之前使用 curl_easy_setopt 为句柄设置)。就像 libcurl 决定关闭连接并且协议是一种在断开连接之前需要命令/响应序列的协议一样。此类协议的示例是FTP,POP3和IMAP。在调用并返回此函数后,任何使用句柄都是非法的。curl_easy_cleanup杀死句柄和与之相关的所有内存!要关闭已与多接口一起使用的简易句柄,请确保先调用curl_multi_remove_handle以在关闭多句柄之前将其从多句柄中删除。在句柄中传入 NULL 指针将使此函数立即返回,无需执行任何操作。

2.4 curl_easy_setopt () [重点]

概要#include <curl/curl.h>CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);描述curl_easy_setopt用于告诉libcurl如何表现。通过设置适当的选项,应用程序可以更改 libcurl 的行为。所有选项都设置了一个选项,后跟一个参数。该参数可以是长整型、函数指针、对象指针或curl_off_t,具体取决于特定选项的期望。请仔细阅读本手册,因为错误的输入值可能会导致 libcurl 表现不佳!在每个函数调用中只能设置一个选项。典型的应用程序在设置阶段使用许多curl_easy_setopt调用。使用此函数调用设置的选项对使用此句柄执行的所有即将进行的传输有效。这些选项不会在传输之间以任何方式重置,因此如果您希望使用不同的选项进行后续传输,则必须在传输之间更改它们。您可以选择使用 curl_easy_reset将所有选项重置回内部默认值。作为 'char *' 参数传递给 libcurl 的字符串由库复制;与指针参数关联的字符串存储可以在curl_easy_setopt返回后被丢弃或重用。此规则的唯一例外是 CURLOPT_POSTFIELDS,但复制字符串CURLOPT_COPYPOSTFIELDS的替代方法具有您需要阅读的一些使用特征。此函数不接受长度超过 CURL_MAX_INPUT_LENGTH (8 MB) 的输入字符串。设置选项的顺序无关紧要。在版本 7.17.0 之前,不会复制字符串。相反,用户被迫保持它们可用,直到libcurl不再需要它们。句柄是来自curl_easy_init或curl_easy_duphandle调用的返回代码。

具体:https://curl.se/libcurl/c/easy_setopt_options.html

部分函数选项解释

1. CURLOPT_URL设置访问URL2. CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA回调函数原型为:size_t function(void *ptr, size_t size, size_t nmemb, void *stream);函数将在libcurl接收到数据后被调用,因此函数多做数据保存的功能,如处理下载文件。CURLOPT_WRITEDATA用于表明CURLOPT_WRITEFUNCTION函数中的stream指针的来源。如果你没有通过CURLOPT_WRITEFUNCTION属性给easy handle设置回调函数,libcurl会提供一个默认的回调函数,它只是简单的将接收到的数据打印到标准输出。你也可以通过CURLOPT_WRITEDATA属性给默认回调函数传递一个已经打开的文件指针,用于将数据输出到文件里。3. CURLOPT_HEADERFUNCTION,CURLOPT_HEADERDATA回调函数原型为 size_t function( void *ptr, size_t size,size_t nmemb, void *stream); libcurl一旦接收到http 头部数据后将调用该函数。CURLOPT_WRITEDATA传递指针给libcurl,该指针表明CURLOPT_HEADERFUNCTION函数的stream指针的来源。4. CURLOPT_READFUNCTIONCURLOPT_READDATAlibCurl需要读取数据传递给远程主机时将调用CURLOPT_READFUNCTION指定的函数,函数原型是:size_tfunction(void *ptr, size_t size, size_t nmemb,void *stream). CURLOPT_READDATA 表明CURLOPT_READFUNCTION函数原型中的stream指针来源。5. CURLOPT_NOPROGRESS,CURLOPT_PROGRESSFUNCTION,CURLOPT_PROGRESSDATA跟数据传输进度相关的参数。CURLOPT_PROGRESSFUNCTION指定的函数正常情况下每秒被libcurl调用一次,为了使CURLOPT_PROGRESSFUNCTION被调用,CURLOPT_NOPROGRESS必须被设置为false,CURLOPT_PROGRESSDATA指定的参数将作为CURLOPT_PROGRESSFUNCTION指定函数的第一个参数6. CURLOPT_TIMEOUT,CURLOPT_CONNECTIONTIMEOUT:CURLOPT_TIMEOUT 由于设置传输时间,CURLOPT_CONNECTIONTIMEOUT 设置连接等待时间7. CURLOPT_FOLLOWLOCATION设置重定位URL8. CURLOPT_RANGE: CURLOPT_RESUME_FROM:断点续传相关设置。CURLOPT_RANGE指定char *参数传递给libcurl,用于指明http域的RANGE头域,例如:表示头500个字节:bytes=0-499表示第二个500字节:bytes=500-999表示最后500个字节:bytes=-500表示500字节以后的范围:bytes=500-第一个和最后一个字节:bytes=0-0,-1同时指定几个范围:bytes=500-600,601-999CURLOPT_RESUME_FROM 传递一个long参数给libcurl,指定你希望开始传递的偏移量。

2.5 curl_easy_perform()

概要#include <curl/curl.h>CURLcode curl_easy_perform(CURL *easy_handle);描述在curl_easy_init和所有curl_easy_setopt调用后调用此函数,并按照选项中所述执行传输。必须使用与返回的curl_easy_init调用相同的输入easy_handle调用它。curl_easy_perform以阻塞方式执行整个请求,并在完成后返回,如果失败,则更早返回。有关非阻塞行为,请参阅curl_multi_perform。您可以对curl_easy_perform进行任意数量的调用,同时使用相同的easy_handle。如果您打算传输多个文件,甚至鼓励您这样做。然后,libcurl 将尝试在后续传输中重复使用相同的连接,从而使操作更快、CPU 密集度更低、网络资源更少。请注意,您必须在调用之间使用curl_easy_setopt来设置以下curl_easy_perform的选项。切勿使用同一easy_handle从两个位置同时调用此函数。让函数先返回,然后再调用它。如果要并行传输,则必须使用多个卷曲easy_handles。网络传输将数据移动到对等方或从对等方移动。应用程序告诉 libcurl 如何通过设置 CURLOPT_WRITEFUNCTION 和 CURLOPT_WRITEDATA 选项来接收数据。为了告诉libcurl要发送什么数据,还有一些替代方案,但两个常见的是CURLOPT_READFUNCTION和CURLOPT_POSTFIELDS。当easy_handle添加到多控点时,curl_easy_perform不能使用它。

4. 代码实现

编译 : gcc demo01_curl.c -I ./curl-7.71.1/_install/include/ -L ./curl-7.71.1/_install/lib/ -lcurl

1. 百度访问

#include <stdio.h>
#include <curl/curl.h>typedef unsigned int bool;//数据类型别名用typedef  有分号
#define true 1            //宏定义(替换)用define         无冒号
#define false 0bool getUrl(char *filename)//GET请求
{CURL *curl;CURLcode res;FILE *fp;if ((fp = fopen(filename, "w")) == NULL)  // 返回结果用文件存储return false;struct curl_slist *headers = NULL;headers = curl_slist_append(headers, "Accept: Agent-007");curl = curl_easy_init();    // 初始化if (curl){//curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");// 代理curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);// 改协议头curl_easy_setopt(curl, CURLOPT_URL,"http://www.baidu.com");curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); //将返回的http头输出到fp>指向的文件,//即为filename文件,而主函数传入的参数是 /tmp/get.html,即为真正保存在get.html文件中curl_easy_setopt(curl, CURLOPT_HEADERDATA, fp); //将返回的html主体数据输出到fp指向的文件res = curl_easy_perform(curl);   // 执行if (res != 0) {curl_slist_free_all(headers);  //释放句柄curl_easy_cleanup(curl);}fclose(fp);return true;}
}
bool postUrl(char *filename)//POST请求
{CURL *curl;CURLcode res;FILE *fp;if ((fp = fopen(filename, "w")) == NULL)return false;curl = curl_easy_init();if (curl){curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookie.txt"); // 指定cookie文件curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "&logintype=uid&u=xieyan&psw=xxx86");    // 指定post内容:用户信息 字段之间&连接,尝试登陆新浪邮箱//curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");curl_easy_setopt(curl, CURLOPT_URL, " http://mail.sina.com.cn/cgi-bin/login.cgi ");   // 指定urlcurl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);res = curl_easy_perform(curl);//执行curl_easy_cleanup(curl);}fclose(fp);return true;
}int main(void)
{       getUrl("/tmp/get.html");postUrl("/tmp/post.html");
}

2. 回调函数使用

#include <stdio.h>
#include <curl/curl.h>
#include <string.h>typedef unsigned int bool;//数据类型别名用typedef  有分号#define true 1            //宏定义(替换)用define         无冒号
#define false 0size_t readData( void *ptr, size_t size, size_t nmemb, void *stream){char buf[1024] = {'\0'}; strncpy(buf,ptr,1024);printf("==========get data===========\n");printf("%s\n",buf);
}bool getUrl(char *filename)//GET请求
{CURL *curl;CURLcode res;FILE *fp;if ((fp = fopen(filename, "w")) == NULL)  // 返回结果用文件存储return false;struct curl_slist *headers = NULL;headers = curl_slist_append(headers, "Accept: Agent-007");curl = curl_easy_init();    // 初始化if (curl){//curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");// 代理curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);// 改协议头curl_easy_setopt(curl,CURLOPT_URL,"http://www.baidu.com");// 模式改为 CURLOPT_WRITEFUNCTION , 使用 readData 回调函数curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, readData);                 res = curl_easy_perform(curl);   // 执行if (res != 0) {curl_slist_free_all(headers);  //释放句柄curl_easy_cleanup(curl);}fclose(fp);return true;}
}
int main(void)
{getUrl("/tmp/get.html");
}

3.接入人脸识别

人脸识别平台 :http://netocr.com/

#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>typedef unsigned int bool;//数据类型别名用typedef  有分号#define true 1            //宏定义(替换)用define         无冒号
#define false 0
char buf[1024] = {'\0'}; size_t readData( void *ptr, size_t size, size_t nmemb, void *stream){strncpy(buf,ptr,1024);
}bool postUrl()//POST请求
{CURL *curl;CURLcode res;curl = curl_easy_init();char *key = "你的key";char *secret = "你的secret";int typeid = 21 ; char *format = "xml";int fd ; int filelen ;// 调用base64 指令,将文件保存 tmpFile 文件 system("base64 R-C1.jpg > tmpFile");fd = open("./tmpFile",O_RDWR);// 获取文件大小filelen = lseek(fd,0,SEEK_END);// 光标移动至最前方lseek(fd,0,SEEK_SET);char *img1 = (char*)malloc(filelen + 2); // 内存分配memset(img1,0,filelen + 2);read(fd,img1,filelen);close(fd);system("base64 R-C2.jpg > tmpFile");fd = open("./tmpFile",O_RDWR);filelen = lseek(fd,0,SEEK_END);lseek(fd,0,SEEK_SET);char *img2 = (char*)malloc(filelen + 2); memset(img2,0,filelen + 2);read(fd,img2,filelen);close(fd);char *postStr = (char * )malloc(strlen(key) + strlen(secret) + strlen(img1) + strlen(img2));sprintf    (postStr,"&img1=%s&img2=%s&key=%s&secret=%s&typeId=%d&format=%s",img1,img2,key,secret,typeid,format);       //printf("%s",postStr);if (curl){curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postStr);    curl_easy_setopt(curl, CURLOPT_URL, "https://netocr.com/api/faceliu.do");   // 指定urlcurl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, readData);res = curl_easy_perform(curl);//执行curl_easy_cleanup(curl);if(strstr(buf,"是") != NULL){printf("人脸检测成功\r\n");}}return true;
}int main(void)
{       postUrl();
}

liunx - libcurl相关推荐

  1. 后端开发之libcurl库编译与安装

    curl 是以URL语法来传输输出的一个命令行工具.libcurl 是对对其功能的封装,实现了命令行工具的所有功能. curl 支持HTTP.HTTPS.FTP.FTPS.DICT.TELNET.LD ...

  2. libcurl 客户端实例

    参考库 libftp (though it's in C) ftplib (again, looks like C) libCurl seems to have FTP capabilities. a ...

  3. shell5.0密钥_8.使用Xshell5密钥登录liunx

    系统:Centos7 工具:Xshell_5.0.0.37_setup.1459931786 工具获取地址:链接:https://pan.baidu.com/s/1bpDCBzp 密码:fo98 用到 ...

  4. libcurl多线程下载开发过程中需要注意的一个问题

    使用libcurl进行多线程开发,发现明明已经接收到正确的文件长度的数据,可是我却看到文件长度值比真实长度,计算其md5自然也会出错. 这不是我所希望看到.究竟是什么情况导致的呢? 后来发现,线程池销 ...

  5. libcurl选项CURLOPT_WRITEDATA中的“坑”

    最近在利用libcurl进行C++程序开发,几次遇到这个问题,现在特抽时间抽时间将其记录下来. CURLOPT_WRITEDATA这个选项在C++中使用时就要注意了, #include <cur ...

  6. libcurl使用多线程下载大文件源码示例!

    使用libcurl多线程下载大文件的基本思想: 首选打开文件,将文件等分为指定的片段,使用http range下载,一个线程下载一个片段,当线程下载片段时,它们将数据写到打开文件的指定位置,类似BT文 ...

  7. libcurl 编程进度条和range请求源码示例

    在下面的源码中,我将展示如何使用libcurl提供的进度条功能,以及如何发送range请求, 同时提供了限速功能. 源码如下: //g++ -g curl_range.cpp -o curl_rang ...

  8. libcurl下载限速编程调研

    目前的业务需求是, 要求下载过程中, 能够恰当控制下载速度? 如何实现? 我想到了libcurl中提供的下载限速选项.现在探讨如下. 我找到Ubuntu 14.04.01的iso大文件, 使用libc ...

  9. liunx查看python的site-packages路径

    有时候我们在liunx上想修改查看python的包路径可以试试以下命令 from distutils.sysconfig import get_python_lib print(get_python_ ...

最新文章

  1. unity片元着色器中获取屏幕坐标_Unity踩坑笔记(持续更新)
  2. 5000元性价比高的笔记本_2018性价比笔记本电脑品牌推荐 5000左右笔记本性价比推荐...
  3. Matlab实现CNN(二)
  4. Migrate Project to Gradle? This project does not use the Gradle build system
  5. 早上运动和晚上运动,哪个更利于减肥?
  6. 【Ngrok】小米球实践-内网穿透【映射本地到外网访问】
  7. GPS接收天线 GPS天线原理(有源天线供电通常由接收机前端通过RF同轴电缆供电。)实际测试GPS接收芯片的SMA天线底座中心孔和底座之间电压3.3V,可以通过SMA接口对天线供电2022.3.30
  8. 51单片机的篮球计分器设计
  9. 吃着火锅唱着歌,我了解到海底捞的信息化太厉害了
  10. stm32 移植 FreeRTOS
  11. 组合模型预测模型_改进著名的nfl预测模型
  12. 进制为2的10次方的世界
  13. AirSim无人机仿真——手柄操作
  14. 小白学习机器学习===谱聚类之NCut切图
  15. java selector 源码_Java NIO——Selector机制源码分析---转
  16. Android 翻页效果 电子书 (转)
  17. eNSP动态NAT实验记录
  18. Python-读取串口数据
  19. ffmpeg m4a 转pcm_使用 FFmpeg 转换音频文件
  20. 电脑键盘部分按键失灵_电脑键盘失灵个别字母不灵怎么办 键盘失灵解决方法...

热门文章

  1. 利用RadonDB实现MySQL分库分表
  2. 如何成为一位合格的嵌入式系统软件工程师
  3. 计算机安全3a是什么,电脑中3A什么意思
  4. ipados怎么整页截屏
  5. 王汎森:如果让我重做一次研究生
  6. 如何取消开机硬盘自检
  7. margin--负的margin的使用
  8. AJAX file uploads in Rails using attachment_fu and responds_to_parent
  9. Unraid安装KMS Docker激活Windows+Office
  10. VMware虚拟机封装windows10:系统封装