libcurl 简单实用

LibCurl是一个开源的免费的多协议数据传输开源库,该框架具备跨平台性,开源免费,并提供了包括HTTPFTPSMTPPOP3等协议的功能,使用libcurl可以方便地进行网络数据传输操作,如发送HTTP请求、下载文件、发送电子邮件等。它被广泛应用于各种网络应用开发中,特别是涉及到数据传输的场景。

官网:curl

下载安装:curl - Download

安装步骤

说明:在编译任何开源代码前可以先看看README, INSTALL等文件, 会提供如何编译的信息。在此教程中通过阅读README和GIT-INFO文 件可以得到很多编译安装信息。 在GIT-INFO 中很明显地说了执行: ./buildconf产生configure配置文件。

./buildconf(产生configure配置文件)
./configure --with-openssl (我是默认安装openssl的)
make
make install(默认库文件安装在/usr/local/lib 头文件安装在/usr/local/include --->安装要root权限)

libcurl库的API接口

(1)初始化curl句柄

cpp 复制代码
CURL* curl = NULL;
curl = curl_easy_init();

(2)设置curl的url

cpp 复制代码
curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:9001/login");

(3)开启post请求开关

cpp 复制代码
curl_easy_setopt(curl, CURLOPT_POST, true);

(4)添加post数据

cpp 复制代码
 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_str);

(5)设定一个处理服务器响应的回调函数

cpp 复制代码
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, deal_response);

(6)给回调函数传递一个形参

cpp 复制代码
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseData);

(7)向服务器发送请求,等待服务器的响应

cpp 复制代码
res = curl_easy_perform(curl);

测试用例(实现网页下载保存):

cpp 复制代码
// 采用CURLOPT_WRITEFUNCTION 实现网页下载保存功能
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
#include <curl/curl.h>
#include <curl/easy.h>




FILE *fp;  //定义FILE类型指针


//这个函数是为了符合CURLOPT_WRITEFUNCTION而构造的,完成数据保存功能
size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)  
{
    int written = fwrite(ptr, size, nmemb, (FILE *)fp);
    return written;
}




 
int main(int argc, char *argv[])
{
    CURL *curl;
    if (argc != 3)
    {
		fprintf(stderr, "usage: %s url filename\n", argv[0]);
		exit(-1);
    }
    curl_global_init(CURL_GLOBAL_ALL);  
    curl = curl_easy_init();
    curl_easy_setopt(curl, CURLOPT_URL, argv[1]);  
 
    if((fp = fopen(argv[2],"w")) == NULL)
    {
        curl_easy_cleanup(curl);
        exit(1);
    }
  //CURLOPT_WRITEFUNCTION 将后继的动作交给write_data函数处理
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);  
    curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    exit(0);
}

编译运行:


该库的使用很简单,首先我们需要调用curl_easy_init()函数对CURL对象进行初始化,接着通过调用curl_easy_setopt()并传入一个访问URL链接,当访问成功后则可curl_easy_perform()函数得到访问结果。

<1>调curl_global_init()接口进行全局初始化

一个进程只需调用一次。如果一次都未调用,curl_easy_init()接口内部会自动调curl_global_init(),因为curl_easy_init()并不是多线程安全,如果两个线程同时调用curl_easy_init(),会概率出现一个线程在没有全局初始化下就进行网络传输导致崩溃,于是强烈建议显示调用curl_global_init()进行libcurl库进行全局初始化。

<2>调curl_easy_init()接口分配一个网络传输对象

因为libcurl是以C语言接口形式提供,所以后续调用的接口都需要提供该接口返回的句柄。

<3>调curl_easy_init()接口分配一个网络传输对象

因为libcurl是以C语言接口形式提供,所以后续调用的接口都需要提供该接口返回的句柄。

curl_easy_setopt()函数第二个参数可以使用多种类型的变量定义,我们可以通过传入不同的常量来定义请求头中的参数,

|------------------------|--------------------------------------------------------------------------------------------------------------|
| CURLOPT_VERBOSE | 设置值为1启用调试输出,此时要设置CURLOPT_DEBUGFUNCTION 调试输出函数,排查问题时使用。 |
| CURLOPT_URL | 设置URL地址 |
| CURLOPT_PUT | 设置HTTP请求方法为PUT,CURLOPT_POST设置HTTP请求方法为POST,要设置HTTP请求方法为DELETE或PATCH,就得用CURLOPT_CUSTOMREQUEST |
| CURLOPT_POSTFIELDS | 设置HTTP请求body内容,CURLOPT_POSTFIELDSIZE设置body大小,如果body内容是以\0结尾,可以不指定body大小。 |
| CURLOPT_HTTPHEADER | 设置HTTP头部,HTTP头部是用curl_slist结构的链表,curl_slist_append()添加HTTP头部,可以调多次添加多个头部,curl_slist_free_all()释放curl_slis对象。 |
| CURLOPT_WRITEFUNCTION | 设置HTTP请求body的数据输出函数,同时可以指定CURLOPT_WRITEDATA作为输出函数的user_data,libcurl会透传user_data。 |
| CURLOPT_TIMEOUT_MS | 设置网络请求总超时值,CURLOPT_CONNECTTIMEOUT_MS设置网络socket连接超时值。 |
| CURLOPT_SSL_VERIFYPEER | 设置0时不校验服务端,HTTPS请求时如果本地没有服务端证书,需要设置为0。 |

官方api文档

libcurl - curl_easy_setopt()

<4>调curl_easy_getinfo()接口获取网络请求响应信息

它类似于curl_easy_setopt()接口,第2个参数指定获取项,第3个参数依第2个参数不同而不同,比较常用的是CURLINFO_RESPONSE_CODE,获取状态码。

<5>调curl_easy_cleanup()接口释放资源

<6>调curl_global_cleanup()接口释放全局资源

下面的demo代码介绍如何使用libcurl库进行HTTP GET和POST请求

cpp 复制代码
#include <stdio.h>
#include <curl/curl.h>
#include <string>


size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    ((std::string*)userdata)->append(ptr, nmemb);
    return nmemb;
}




int main(void)
{
    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL* curl = curl_easy_init();
    if (curl) 
    {        
        curl_easy_setopt(curl, CURLOPT_URL, "https://www.baidu.com");

        // no certificate, not verify server certificate
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);

        std::string response_data;
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_data);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
        CURLcode res = curl_easy_perform(curl);
        if (res != CURLE_OK)
        {
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
                curl_easy_strerror(res));
        }
        else
        {
            long response_code;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
            printf("response code %ld \n", response_code);
            printf("response data : \n ");
            printf(response_data.c_str());
        }

        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();
    return 0;
}

运行结果:

cpp 复制代码
#include <stdio.h>
#include <curl/curl.h>
#include <string>

size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    ((std::string*)userdata)->append(ptr, nmemb);
    return nmemb;
}

int main()
{
    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL* curl = curl_easy_init();
    if (curl)
    {
        // set url
        curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts");

        // no certificate, not verify server certificate
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);

        // set http method
        curl_easy_setopt(curl, CURLOPT_POST, 1);

        // set header
        struct curl_slist * slist = nullptr;
        slist = curl_slist_append(slist, "Content-Type : application/json");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);

        // set body
        std::string body = "{\
            \"title\":\"libcurl post title\",\
            \"body\" : \"libcurl post body\",\
            \"userId\" : 1}";
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());

        // set response callback to read response
        std::string response_data;        
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_data);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
        CURLcode res = curl_easy_perform(curl);
        if (res != CURLE_OK)
        {
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
                curl_easy_strerror(res));
        }
        else
        {
            // get response code
            long response_code;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
            printf("response code %ld \n", response_code);
            printf("response data : \n ");
            printf("%s", response_data.c_str());
        }

        curl_slist_free_all(slist);
        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();
    return 0;
}

运行结果:

相关推荐
iso少年1 分钟前
Go 语言并发编程核心与用法
开发语言·后端·golang
掘金码甲哥3 分钟前
云原生算力平台的架构解读
后端
码事漫谈7 分钟前
智谱AI从清华实验室到“全球大模型第一股”的六年征程
后端
码事漫谈7 分钟前
现代软件开发中常用架构的系统梳理与实践指南
后端
Mr.Entropy34 分钟前
JdbcTemplate 性能好,但 Hibernate 生产力高。 如何选择?
java·后端·hibernate
YDS8291 小时前
SpringCloud —— MQ的可靠性保障和延迟消息
后端·spring·spring cloud·rabbitmq
龚礼鹏1 小时前
Android应用程序 c/c++ 崩溃排查流程二——AddressSanitizer工具使用
android·c语言·c++
qq_401700411 小时前
QT C++ 好看的连击动画组件
开发语言·c++·qt
无限大61 小时前
为什么"区块链"不只是比特币?——从加密货币到分布式应用
后端
洛神么么哒1 小时前
freeswitch-初级-01-日志分割
后端