本文简要介绍libcurl c接口,有一些简单的用c代码编写的例子,或许可以给你带来启发。
libcurl提供了easy和multi两套接口,具体使用哪套接口取决于你的需求。
easy接口是同步、高效、容易使用的文件传输接口,许多应用程序都基于这个接口来构建。
multi接口是异步且在单线程或多线程中提供并发传输,具体如何使用这个接口请参看。
下面会简要介绍easy接口如何使用。
一、主要接口
easy主要接口如下:
curl_easy_init():初始化并获取一个handle。
curl_easy_setopt():设置传输选项。
curl_easy_perfrom():开始传输数据,由于是同步传输,因此,线程会在此阻塞。
curl_easy_getinfo():在传输回调过程中或传输结束之后获取相关信息。
curl_easy_cleanup():清除handle。
二、简单例程
使用easy接口是:首先调用函数curl_easy_init初始化一个easy-session并得到一个handle,接着调用函数curl_easy_setopt设置传输选项,可以设置url也可以设置数据可用时的回调函数,设置完毕后调用函数curl_easy_perfrom传输数据,该过程是同步的,即要么成功要么失败要么一直阻塞,该函数返回后,可以调用函数curl_easy_getinfo获取接收到的数据,最后调用函数curl_easy_cleanup清除handle。这里附上官方的sample.c:
#include
#include
int main(void)
{
curl *curl;
curlcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, curlopt_url, "");
/* example.com is redirected, so we tell libcurl to follow redirection */
curl_easy_setopt(curl, curlopt_followlocation, 1l);
/* perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* check for errors */
if(res != curle_ok)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
需要注意的是:不要在多线程之间共享同一个easy handle,这不安全,原则上每个线程都应该有自己的easy handle用于传输数据;easy handle在完成一次数据通讯后可以被重用。
在编译前需要执行如下指令以确认是否安装必须的包:
#rpm -qa|grep curl
curl-7.15.5-9.el5_6.3
curl-devel-7.15.5-9.el5_6.3
libcurl提供了用于查询包括但不限于编译所需信息的工具curl-config,直接执行curl-config能得到所有功能参数:
#curl-config --cflags
预处理和编译参数。
#curl-config --libs
需要link或者支持的的库。
以sample.c为例可以如下来编译之:
#gcc -o simple simple.c -lcurl
也可以如下来链接所有库:
#gcc $(curl-config --libs) -o simple simple.c
执行上面操作后就编译出可执行文件simple了,执行simple会在屏幕打印出的凯发app官方网站主页信息。
之所以这样是因为libcurl会默认提供一个用于接收数据的回调函数,该函数的默认规则是将接收到的数据打印到标准输出。
当然你也可以手动设置该函调函数以便于自己处理接收到的数据,要做到这点很简单,调用curl_easy_setopt接口函数设置接收数据的回调函数,回调函数原型如下:
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
如下来注册回调函数:
curl_easy_setopt(easy_handle, curlopt_writefunction, write_data);
还可以如下来给回调函数提供一个自定义参数,libcurl透传该参数:
curl_easy_setopt(easy_handle, curlopt_writedata, &internal_struct);
调用函数curl_easy_perfrom执行各种命令后开始接收数据,libcurl可能一次只接收到1字节的数据,也可能接收到好几k的数据,但这都是libcurl内部的行为,对于外部调用curl_easy_perfrom的程序来说是一直阻塞在该函数处,直到出错或者接收完成。
三、问题优化
easy接口使用同步机制,无法像异步一样随意控制无压力,以下两种情况均可能引发curl_easy_perform阻塞卡死:
(1)下载某些大文件时,由于本地路由器流量控制,网络未断开,但是却无法接收到数据。
(2)下载过程中,网络异常中断。
凯发app官方网站的解决方案:
(1)使用multi接口。
multi为异步接口,牺牲了一部分效率但确保了大部分灵活性,当然使用复杂度也相对上升。
(2)设置下载超时时间(curlopt_timeout)
设置超时时间后,curl会在超过此时间后无论正处于什么状态都会跳出堵塞,此种方案适用于小文件的下载,当然你也可以在超时之后重复连接以满足大文件的下载需求。
(3)使用回调函数返回abort value
此种方法是最简单方便的方法。一般这样操作, 首先设置进度回调函数,然后在回调函数里面判断某个时间内有没有接收到数据,如超时则返回非0值。
四、其它接口
此外,还提供了一些有用的接口函数,具体如下:
curl_version():返回一个指向libcurl版本号字符串的指针。
curl_getdate():转换日期字符串为time_t。
curl_formadd():构建多个post表单数据。
curl_formfree():释放之前post构建的数据。
curl_slist_append():构建链表curl_slist。
curl_slist_free_all():释放由curl_slist_append构建的curl_slist。
curl_easy_escape():url编码一个字符串。
curl_easy_unescape():url解码一个字符串。
更多信息请参见,要深入理解libbcurl请参看,也可以参看。
阅读(9251) | 评论(1) | 转发(0) |