本文简要介绍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, "http://example.com");
                    /* 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会在屏幕打印出http://example.com的主页信息。
        之所以这样是因为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)下载过程中,网络异常中断。
        解决方案:
        (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请参看这里,也可以参看这里

        
12-22 08:53