在这里插入图片描述

🍎什么是LIBCURL?

libcurl是一个跨平台的开源网络协议库,支持http、https、rtsp等多种协议,使用libcurl可以很简单的完
成http的下载工作
libcurl主要提供两种发送http请求的方式

  1. easy interface:采用阻塞的方式发送单条请求
  2. multi interface:采用组合的方式可以一次性发送多条请求数据,且多个下载请求时异步进行的

🍎安装

我这里学习使用的环境是Ubuntu 16.04,安装比较简单,直接使用apt-get包管理器安装即可
sudo apt-get install libcurl4-openssl-dev

简单测试一下是否安装成功
curl http://www.baidu.com/

🍎学习使用

学习这个libcurl库是在学习完jsoncpp库之后的,因为作业有用到要下周远程服务器上的json文档,再将文档解析输出。
libcurl库的学习,并不深入,只是了解了怎么使用它,有哪种方法?

🍇1. 有哪些方法?

这里我了解到的有两种:
1. 一种是库里提供的类似于api的使用方法,就是上面测试安装是否成功的用法。使用很简单,就是curl -X 'GET/POST' 'url',-X是其中一个参数,具体可以看下其他博主得,特别详细
2. 另一种就是代码编程实现了,具体往下看

🍇2. 代码实现easy interface

  • libcurl传输任务大致流程
1. 调用curl_global_init()初始化libcurl;
2. 调用curl_easy_init()得到easy interface型指针,使用该指针作为easy接口中其他函数的输入;
3. 调用curl_easy_setopt()设置传输选项,如url地址、http头等,CURLOPT_URL为必须选项,该
函数为整个模块的核心;
4. 根据curl_easy_setopt()实现回调函数;
5. 调用curl_easy_perform()传输数据,开始http的请求工作,该接口是一个阻塞的接口;
6. 调用curl_easy_cleanup()清空句柄;
7. 调用curl_easy_cleanup()释放内存;
  • curl_easy_setopt()简介
    函数原型:CURLcode curl_easy_setopt(CURL *handle, CURLoption, parameter);
    所有的curl程序中都要频繁的使用该函数,它告诉curl库程序将有什么样的行为
    参数:1. CURL类型的指针、2. 各种CURLoption类型的选项、3. parameter这个参数取决于第二个参数
    几个常用的参数及使用方法
1. CURLOPT_URL这个选项必须要有,设置请求的URL。
如果URL参数不协商协议头(如http://),那么函数会自己进行猜解所给的主机上使用的是哪一种协议。
假如给的这个地址是一个不被支持的协议,那么在其后执行curl_easy_perform()函数或curl_multi_perform()函数时,
libcurl将返回错误(CURL_UNSUPPORTED_PROTOCOL).
这个选项是唯一一个在curl_easy_perform()调用之前就一定要设置的选项

2. CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA
1)CURLOPT_WRITEFUNCTION选项用于设置接收数据回调函数,
回调函数原型为: size_t function(void *ptr, size_t size, size_t nmemb, void *stream);
函数将在libcurl接收到数据后被调用,因此函数多做数据保存的功能,如处理下载文件。
2)CURLOPT_WRITEDATA选项用于指定CURLOPT_WRITEFUNCTION函数中的stream指针的来 源。
3)如果没有通过CURLOPT_WRITEFUNCTION属性给easy handle设置回调函数,
libcurl会提供一个默认的回调函数,它只是简单的将接收到的数据打印到标准输出。
也可以通过CURLOPT_WRITEDATA属性给默认回调函数传递一个已经打开的文件指针,用于将数据输出到文件里。

3. CURLOPT_HEADERFUNCTION,CURLOPT_HEADERDATA
1)CURLOPT_HEADERFUNCTION设置接收到http头的回调函数,
原型为:size_t function(void *ptr,size_t size,size_t nmemb, void *stream);
libcurl一旦接收到http 头部数据后将调用该函数。
2)CURLOPT_HEADERDATA传递指针给libcurl,该指针表明CURLOPT_HEADERFUNCTION函数的stream指针的来源

🍇3. 代码实现,提供的示例

#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#include <unistd.h>
#define CURL_WAIT_TIMEOUT_MSEC 60000 

#define CURL_MULTI_MAX_NUM 5

static size_t recive_data_fun(void *ptr, size_t size, size_t nmemb, void *stream)
{
    return fwrite(ptr, size,nmemb, (FILE*)stream);
}

static size_t read_head_fun(void *ptr, size_t size, size_t nmemb, void *stream)
{
    char head[2048] = {0};
    memcpy(head, ptr, size*nmemb + 1);
    printf("%s \n", head);
    return size *nmemb;
}

int main(int argc, char **argv)
{
    if(argc <3)
    {
        printf("arg1 is url; arg2 is out file\n");
        return -1;
    }

    char* url = strdup(argv[1]);
    char* filename = strdup(argv[2]);
    CURL* curl_handle;
    CURLcode res;
    FILE* save_file = fopen(filename, "w");
    if(save_file == NULL)
    {
        printf("open save file fail!\n");
    return -1;
    } 
    //初始化,必须调用的第一个函数,返回handle,作为easy接口中其他函数的输入
    curl_handle = curl_easy_init();
    if(curl_handle)
    {
        //set download url
        curl_easy_setopt(curl_handle, CURLOPT_URL, url);
        //set download file
        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, save_file);
        //set call back fun
        curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, recive_data_fun);
        set call back fun
        curl_easy_setopt(curl_handle, CURLOPT_HEADRFUNCTION, read_head_fun);
        #ifdef CURL_DEBUG
        curl_easy_setopt(curl_handle,CURL_VERBOSE, 1);
        #endif
        //start downloadres = curl_easy_perform(curl_handle);
        printf("curl fetch code %d\n", res);
    } 
    //release
    if(save_file)
    {
        fclose(save_file);
        save_file = NULL;
    }
    if(curl_handle)
    {
        curl_easy_cleanup(curl_handle);
    }
    if(curl)
    {
        free(url);
    }
    return 0;
}

编译文件的时候,与使用jsoncpp库一样,需要指定链接库-lcurl
g++ -o * *.cpp -lcurl
在这里插入图片描述
在这里插入图片描述

🍎仿照示例编写一个可传入不同url的函数

下面的函数,就是在作业中,用于下载远程服务器中的文档到本地的例子

size_t process_data(void *buffer, size_t size, size_t nmemb, void * user_p)
{
    FILE *fp = (FILE *)user_p;
    size_t return_size = fwrite(buffer, size, nmemb, fp);
    return return_size;
}

int CurlDeviceJson(char * i_pUrl)
{
    char json_name[16] = {0};
    // 1. Initialize libcurl
    CURLcode return_code;
    return_code = curl_global_init(CURL_GLOBAL_WIN32);
    if(CURLE_OK != return_code)
    {
        GBLog_Log(LL_ERROR, "init libcurl failed.");
    }

    // 2. Get easy handle
    CURL * easy_handle = curl_easy_init();
    if(NULL == easy_handle)
    {
        GBLog_Log(LL_ERROR, "get a easy handle failed.");
        curl_global_cleanup();
        return -1;
    }
    // 2.1 Create a directory for saving json files
    system("mkdir -p /tmp/device_json/");

    // 2.2 Create a directory for saving json files
    FILE * fp;
    if(strstr(i_pUrl, "network"))
    {
        system("rm -rf ./network.json");
        fp = fopen("network.json", "ab+");
    }
    else
    {
        fp = fopen("unkown.json", "ab+");
    }

    // 3. Set the easy handle attribute and URL
    curl_easy_setopt(easy_handle, CURLOPT_URL, i_pUrl);
    curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, &process_data);
    curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, fp);

    // 4. Execute data request
    curl_easy_perform(easy_handle);

    // 5. Release resources
    fclose(fp);
    curl_easy_cleanup(easy_handle);
    curl_global_cleanup();

    return 0;
}

在这里插入图片描述

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐