🍎什么是LIBCURL?
libcurl是一个跨平台的开源网络协议库,支持http、https、rtsp等多种协议,使用libcurl可以很简单的完
成http的下载工作
libcurl主要提供两种发送http请求的方式
- easy interface:采用阻塞的方式发送单条请求
- 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;
}