精华内容
下载资源
问答
  • libcurl 使用

    2018-04-02 15:23:00
    以下是如何使用libcurl的例子. 一、常用函数 1) libcurl的全局初始化及释放 CURLcode curl_global_init(long flags) flags:CURL_GLOBAL_ALL //初始化所有的可能的调用。 ...

    关于libcurl的文章网络上很多, 这里不再描述. 以下是如何使用libcurl的例子.

     
    一、常用函数
        1) libcurl的全局初始化及释放
    1.      CURLcode curl_global_init(long flags) 
                    flags: CURL_GLOBAL_ALL     //初始化所有的可能的调用。
                           CURL_GLOBAL_SSL     //初始化支持 安全套接字层。
                           CURL_GLOBAL_WIN32   //初始化win32套接字库。
                           CURL_GLOBAL_NOTHING //没有额外的初始化。
    1.      void     curl_global_cleanup(void)
          应该在程序开始时调用初始化函数. 虽然不调用这个初始化函数, libcurl会在curl_easy_init()函数中自动调用. 但在多线程处理时, 可能会出现多次自动调用的情况.
     
        2) 初始化下载handle及释放
    1.      CURL *curl = curl_easy_init();
    2.      curl_easy_cleanup(curl);
        3) 设置下载属性. 及常用参数. 
    1.      CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
           
          1. 设置下载数据的回调函数.      
    1.      option:      
    2.      CURLOPT_WRITEFUNCTION //设置回调函数
             回调函数原型为: size_t function( void *ptr, size_t size, size_t nmemb, void *userp);           函数将在libcurl接收到数据后被调用。
             void *ptr是下载回来的数据.
             void *userp是用户指针, 用户通过这个指针传输自己的数据.
    1.      CURLOPT_WRITEDATA 
    2.       设置回调函数中的void *userp指针的来源。
          2. 下载进度控制.
    1.      option:
    2.      CURLOPT_NOPROGRESS  
    3.        为了使CURLOPT_PROGRESSFUNCTION被调用. CURLOPT_NOPROGRESS必须被设置为false.
    4.      CURLOPT_PROGRESSFUNCTION
    5.        CURLOPT_PROGRESSFUNCTION 指定的函数正常情况下每秒被libcurl调用一次.
    6.      CURLOPT_PROGRESSDATA
    7.        CURLOPT_PROGRESSDATA指定的参数将作为CURLOPT_PROGRESSFUNCTION指定函数的参数. 
    8.      整个处理与下载数据回调的处理相同. 
    9.      3. 其它常用属性. 
           option:
    10.      CURLOPT_URL
    11.        设置访问的URI.
    12.      CURLOPT_NOSIGNAL
    13.        屏蔽其它信号.
    14.      CURLOPT_HEADER
    15.        取数据时连同HTTP头部一起取回.
    16.      CURLOPT_HEADERFUNCTION
    17.      CURLOPT_HEADERDATA
    18.        只取HTTP头部数据, 处理与下载数据回调的处理相同. 
    19.      CURLOPT_TIMEOUT
    20.        超时时间.
    21.      CURLOPT_CONNECTIONTIMEOUT
    22.        连接等待时间.
    23.      CURLOPT_FOLLOWLOCATION
    24.      设置支持302重定向
    25.    CURLOPT_RANGE
    26.       断点续传, 指定传输分片, 格式:"0-200"
        4) 开始下载
    1.      CURLcode curl_easy_perform(CURL *handle);
     
    二、例程
        获取网站包括HTTP头部信息在内的500字节数据.
    1. size_t callback_get_head(void *ptr, size_t size, size_t nmemb, void *userp)
     {
        strcat( userp, ptr);
        return size * nmemb;     //必须返回这个大小, 否则只回调一次, 不清楚为何.
     }
     
     void *get_head_thread(void *)
     {
        CURL *curl = curl_easy_init();
        
        curl_easy_setopt(curl, CURLOPT_URL, "www.163.com"); //设置下载的URI
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20);        //设置超时
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);        //屏蔽其它信号
        curl_easy_setopt(curl, CURLOPT_HEADER, 1);          //下载数据包括HTTP头部
        curl_easy_setopt(curl, CURLOPT_RANGE, "0-500");     //用于断点续传, 设置下载的分片
        
        char buffer[MAXHEADLEN] = {0x0};
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback_get_head); //设置下载数据的回调函数
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer);  
     
        curl_easy_perform(curl);  
        curl_easy_cleanup(curl);
     
        //此时网站HTTP头信息已经存放在buffer内.
     }
    struct FtpFile {
    std::string filename;
    FILE *stream;
    };
    
    static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
    {
    struct FtpFile *out=(struct FtpFile *)stream;
    if(out && !out->stream)
    {
    out->stream=fopen(out->filename.c_str(), "wb");//打开文件进行写入
    if(!out->stream)
    {
    return -1;
    qDebug("&&&&&& write file %s err, open failed. \n ", out->filename.c_str());
    }
    }
    return fwrite(buffer, size, nmemb, out->stream);
    }
    
    int Downloader::DownloadFile(string url, string filePath)
    {
    CURL *curl;
    CURLcode res;
    struct FtpFile ftpfile={ filePath, NULL };
    
    curl = curl_easy_init(); //初始化一个curl指针
    
    if(curl)
    {
    //设置远端地址
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    
    //执行写入文件流操作
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);//当有数据被写入,回调函数被调用,
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile); //设置结构体的指针传递给回调函数
    
    //启用时会汇报所有的信息,存放在STDERR或指定的CURLOPT_STDERR中
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    
    curl_easy_setopt(curl, CURLOPT_USERPWD, "SUREN:SUREN");
    
    //写入文件
    res = curl_easy_perform(curl);
    
    //释放curl对象
    curl_easy_cleanup(curl);
    
    if(res != CURLE_OK)
    {
    qDebug("&&&&&& download failed %s, url: %s \n", curl_easy_strerror(res), url.c_str());
    }
    else
    {
    //qDebug("&&&&&& download succeed. \n");
    }
    }
    
    if(NULL != ftpfile.stream)
    {
    //关闭文件流
    fclose(ftpfile.stream);
    }
    
    return 0;
    }
    

      

    转载于:https://www.cnblogs.com/wangjian8888/p/8693715.html

    展开全文
  • libcurl使用

    2017-01-18 22:17:36
    Libcurl方法一: 下载源码 git clone http://github.com/curl/curl.git 编译和安装 cd curl ./buildconf ./configure make sudo make install 安装完毕之后,头文件 /usr/local/include/curl /usr/local/lib...

    Libcurl

    方法一:

    cd curl
    ./buildconf
    ./configure
    make
    sudo make install
    安装完毕之后,头文件
    /usr/local/include/curl
    /usr/local/lib/libcurl.so

    方法二:

    ubuntu:
    sudo apt-get install curl
    sudo apt-get install libcurl4-openssl-dev
    头文件:/usr/include/curl
    库目录:/usr/lib

    基本流程是:

    • 初始化CURL环境
    • 创建CURL对象
    • 设置CURL
    • 执行CURL

    使用

    #include <stdio.h>
    #include <curl/curl.h>
    bool getUrl(char *filename)
    {
        CURL *curl;
        CURLcode res;
        FILE *fp;
        if ((fp = fopen(filename, "w")) == NULL)  // 返回结果用文件存储
            return false;
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "Accept: Agent-007");
        curl = curl_easy_init();    // 初始化
        if (curl)
        {
            //curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");// 代理
            curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);// 改协议头
            curl_easy_setopt(curl, CURLOPT_URL,"http://www.baidu.com");
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); //将返回的http头输出到fp指向的文件
            curl_easy_setopt(curl, CURLOPT_HEADERDATA, fp); //将返回的html主体数据输出到fp指向的文件
            res = curl_easy_perform(curl);   // 执行
            if (res != 0) {
    
                curl_slist_free_all(headers);
                curl_easy_cleanup(curl);
            }
            fclose(fp);
            return true;
        }
    }
    bool postUrl(char *filename)
    {
        CURL *curl;
        CURLcode res;
        FILE *fp;
        if ((fp = fopen(filename, "w")) == NULL)
            return false;
        curl = curl_easy_init();
        if (curl)
        {
            curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookie.txt"); // 指定cookie文件
            curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "&logintype=uid&u=xieyan&psw=xxx86");    // 指定post内容
            //curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");
            curl_easy_setopt(curl, CURLOPT_URL, " http://mail.sina.com.cn/cgi-bin/login.cgi ");   // 指定url
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
            res = curl_easy_perform(curl);
            curl_easy_cleanup(curl);
        }
        fclose(fp);
        return true;
    }
    int main(void)
    {
        getUrl("/tmp/get.html");
        postUrl("/tmp/post.html");
    }
    展开全文
  • libcurl 使用demo

    2015-10-30 11:33:40
    libcurl使用demo,获取http头文件信息
  • libcurl使用心得

    2019-10-06 01:03:00
    libcurl使用心得 libcurl使用心得 - 浪迹天涯 - C++博客libcurl使用心得Libcurl为一个免费开源的,客户端url传输库,支持FTP,FTPS,TFTP,HTTP,HTTPS,GOPHER,TELNET,DICT,FILE和LDAP,跨平...

    libcurl使用心得 - 浪迹天涯 - C++博客

    libcurl使用心得

    Libcurl为一个免费开源的,客户端url传输库,支持FTPFTPSTFTPHTTPHTTPSGOPHERTELNETDICTFILELDAP,跨平台,支持WindowsUnixLinux等,线程安全,支持Ipv6。并且易于使用。

    http://curl.haxx.se/libcurl/

    http://curl.haxx.se/libcurl/ 下载一个稳定的版本,注意选择OS
    在使用之前请大家多阅读libcurl的文档:因为如果要实际运用到项目中,最好对libcurl有具体的了解,具体在
    http://curl.haxx.se/libcurl/c/
    curl_easy_setopt()
    curl_easy_perform()
    curl_easy_getinfo()
    这三个函数的使用上,需要多去钻研,多看Samples,你才能灵活使用libcurl。
    感谢这篇文章:
    http://blog.163.com/xu_chao2000/blog/static/27770610200801303252802/
    给了我许多启发,再次感谢!

    给出我的一个简单的代码例子:
    说明:
    1.关键在curl_easy_setopt函数设置option,可以设置ftp,http,get,post等许多选项,请根据具体使用情况设置。

    2.对取回来的数据需要进行判断,比如http下载文件,如果文件不存在,需要进行处理。因为writer是可以将buf填充404 not found等网页内容的,不能将这个内容当成文件内容,所以需要判断http web返回来的code,进行判断。

    3.我有个问题,就是想得到服务器上filename的具体名称,verbose调试已经返回了,但是我在getinfo的时候,试过好多选项,但未找到这个存放真实服务器文件名的选项,如果有知道的麻烦告诉我,谢谢了!

    #include "curl/curl.h"
    #pragma comment(lib, 
    "libcurl.lib")

    long writer(void
    *data, int size, int nmemb, string &content);
    bool  CurlInit(CURL 
    *&curl, const char* url,string &content);
    bool  GetURLDataBycurl(const char* URL, string 
    &content);

    void main()
    {
        char *url ="http://www.baidu.com/img/baidu.gif";
        string content;
        
    if ( GetURLDataBycurl(url,content))
        
    {
            printf(
    "%s\n",content);

        }

        getchar();
    }


    bool CurlInit(CURL 
    *&curl, const char* url,string &content)
    {
        CURLcode code;
        string error;
        curl 
    = curl_easy_init();
        
    if (curl == NULL)
        
    {
            printf( 
    "Failed to create CURL connection\n");
            
    return false;
        }

        code 
    = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
        
    if (code != CURLE_OK)
        
    {
            printf( 
    "Failed to set error buffer [%d]\n", code );
            
    return false;
        }

        curl_easy_setopt(curl, CURLOPT_VERBOSE, 
    1L);
        code 
    = curl_easy_setopt(curl, CURLOPT_URL, url);
        
    if (code != CURLE_OK)
        
    {
            printf(
    "Failed to set URL [%s]\n", error);
            
    return false;
        }

        code 
    = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
        
    if (code != CURLE_OK)
        
    {
            printf( 
    "Failed to set redirect option [%s]\n", error );
            
    return false;
        }

        code 
    = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
        
    if (code != CURLE_OK)
        
    {
            printf( 
    "Failed to set writer [%s]\n", error);
            
    return false;
        }

        code 
    = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content);
        
    if (code != CURLE_OK)
        
    {
            printf( 
    "Failed to set write data [%s]\n", error );
            
    return false;
        }

        
    return true;
    }


    long writer(void
    *data, int size, int nmemb, string &content)
    {
        long sizes 
    = size * nmemb;
        string temp(data,sizes);
        content 
    += temp; 
        
    return sizes;
    }


    bool GetURLDataBycurl(const char* URL,  string
    &content)
    {
        CURL 
    *curl = NULL;
        CURLcode code;
        string error;

        code 
    = curl_global_init(CURL_GLOBAL_DEFAULT);
        
    if (code != CURLE_OK)
        
    {
            printf( 
    "Failed to global init default [%d]\n", code );
            
    return false;
        }
     
        
        
    if ( !CurlInit(curl,URL,content) )
        
    {
            printf( 
    "Failed to global init default [%d]\n" );
            
    return PM_FALSE;
        }

        code 
    = curl_easy_perform(curl);
        
    if (code != CURLE_OK)
        
    {
            printf( 
    "Failed to get '%s' [%s]\n", URL, error);
            
    return false;
        }

        long retcode 
    = 0;
        code 
    = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE , &retcode); 
        
    if ( (code == CURLE_OK) && retcode == 200 )
        
    {
            double length 
    = 0;
            code 
    = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD , &length); 
            printf(
    "%d",retcode);
            FILE 
    * file = fopen("1.gif","wb");
            fseek(file,
    0,SEEK_SET);
            fwrite(content.c_str(),
    1,length,file);
            fclose(file);

            
    //struct curl_slist *list;
            
    //code = curl_easy_getinfo(curl,CURLINFO_COOKIELIST,&list);
            
    //curl_slist_free_all (list);

            
    return true;
        }

        
    else
        
    {
        
    //    debug1( "%s \n ",getStatusCode(retcode));
            return false;
        }

        curl_easy_cleanup(curl);
        
    return false;
    }

    posted on 2012-05-22 10:52 lexus 阅读(...) 评论(...) 编辑 收藏

    转载于:https://www.cnblogs.com/lexus/archive/2012/05/22/2512949.html

    展开全文
  • libcurl 使用方法简介

    万次阅读 多人点赞 2018-09-30 10:09:18
    libcurl 使用方法简介背景简介使用方法1、easy interface使用方法2、multi interface使用方法 背景 最近想做一个简单的HLS拉流程序,HTTP的下载部分觉得采用libcurl来进行比较合适及方便,所以先介绍libcurl的基本...

    背景

    最近想做一个简单的HLS拉流程序,HTTP的下载部分觉得采用libcurl来进行比较合适及方便,所以先介绍libcurl的基本用法,然后使用libcurl完成一个简单的下载小程序。

    简介

    libcurl是一个跨平台的开源网络协议库,支持http, https, rtsp等多种协议 。libcurl同样支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传, HTTP基本表单上传,代理,cookies,和用户认证。
    所以,使用libcurl,可以很简单的完成HTTP的下载工作,为HLS模块的拉流部分提供简单有效的HTTP请求方法。
    想要知道更多关于libcurl的介绍,可以到官网 上去了解,在这里不再详述。(官网地址 http://curl.haxx.se/)

    libcurl主要提供了两种发送HTTP请求的方式,分别是easy interface方式和multi interface方式,前者是采用阻塞的方式发送单条请求,后者采用组合的方式可以一次性发送多条请求数据,且多个下载请求是异步进行的。

    使用方法

    1、easy interface使用方法

    easy interface主要方法如下:

    1)初始化,这个函数必须是调用的第一个函数,并且它返回一个easy interface
    的handle,使用该handle作为easy接口中其他函数的输入。

     CURL *curl_easy_init( );
    

    2)当操作完成时,此调用必须有相应的调用curl_easy_cleanup() 来释放handle。

    void curl_easy_cleanup(CURL * handle );
    

    3)设置此次传输的一些基本参数,如url地址、http头、cookie信息、发送超时时间等,其中,CURLOPT_URL是必设的选项。
    该函数是整个模块的核心,使用该函数,我们可以设置很多相关操作,正是由于该函数的存在,才另libcurl变的简单且具备多种可操作性。
    curl_easy_setopt一些经常使用的方式,会在后面补充

     CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parametr);
    

    4)在上述准备工作已经完成后,可以调用curl_easy_perform函数,则会开始HTTP的请求工作。该接口是一个阻塞的接口。

     CURLcode curl_easy_perform(CURL * easy_handle );
    

    5)请求过程中,可以使用下面函数,获取HTTP该次请求的相关信息,包括response
    code,下载的URL,下载速度等。该函数对于一次请求不是必须的。

      CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... ); 
    

    第 2 个参数有众多选项,每个选项都有其相应的含义,第3个参数根据参数2,会有不同类型。常用的info如下:

    1、CURLINFO_RESPONSE_CODE 取得response code,要求第 3 个参数是个 long
    型的指针。如果TCP就连接不上,值为0。 CURLINFO_EFFECTIVE_URL
    取得本最终生效的URL,也即是如果有多次重定向,获取的值为最后一次URL,要求第 3 个参数是个 char 型的指针。
    2、CURLINFO_SIZE_DOWNLOAD 获取下载字节数,要求第 3 个参数是个 double
    型的指针。注意,这个字节数只能反映最近一次的下载。
    3、CURLINFO_SPEED_DOWNLOAD 获取平均下载数据,该选项要求传递一个
    double 型参数指针,这个速度不是即时速度,而是下载完成后的速度,单位是 字节/秒
    4、CURLINFO_TOTAL_TIME
    获取传输总耗时,要求传递一个 double 指针到函数中,这个总的时间里包括了域名解析,以及 TCP 连接过程中所需要的时间。
    5、CURLINFO_CONTENT_TYPE 该选项获得 HTTP 中从服务器端收到的头部中的 Content-Type 信息。
    6、CURLINFO_CONTENT_LENGTH_DOWNLOAD 获取头部content-length,要求第 3 个参数是个 double
    型的指针。如果文件大小无法获取,那么函数返回值为 -1 。

    使用上面的几个函数,我们就可以完成一个简单的HTTP下载程序:

    CURL *curl = curl_easy_init();
    if(curl) {
      CURLcode res;
      curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
      res = curl_easy_perform(curl);
      curl_easy_cleanup(curl);
    }
    

    curl_easy_setop简介:
    函数原型:

    CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
    

    描述:
    这个函数几乎所有的curl 程序都要频繁的使用它,它告诉curl库程序将有如何的行为。 (这个函数有些像ioctl函数)
    参数:
    1 CURL类型的指针
    2 各种CURLoption类型的选项.。这个参数的取值很多,具体的可以查看man手册。
    3 parameter 这个参数 既可以是个函数的指针,也可以是某个对象的指针,也可以是个long型的变量。它用什么这取决于第二个参数。

    下面介绍几个常用的参数及使用方法:

    1. CURLOPT_URL 这个选项必须要有,设置请求的URL ,如果URL参数不写上协议头(如 “http://” 或者 "ftp:// 等等),那么函数会自己进行猜解所给的主机上用的是哪一种服务协议。
      假如给的这个地址是一个不被支持的协议,那么在其后执行curl_easy_perform() 函数或 curl_multi_perform() 函数时,libcurl将返回错误(CURLE_UNSUPPORTED_PROTOCOL)。 这个选项是唯一一个在 curl_easy_perform()调用之前就一定要设置的选项。
    1. 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属性给默认回调函数传递一个已经打开的文件指针,用于将数据输出到文件里。
    1. 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指针的来源。

    和上面两组类似的,这样对应的回调选项还有很多,使用方法也类似,如: CURLOPT_READFUNCTION/ CURLOPT_READDATA;

    1. CURLOPT_HTTPHEADER
      libcurl有自己默认的请求头,如果不符合我们的要求,可以使用该选项自定义请求头。可以使用curl_slist_append进行自定义,重设,如果设置请求参数为空,则相当于删除该请求头。
    1. CURLOPT_USERAGENT
      该选项要求传递一个以 ‘\0’ 结尾的字符串指针,这个字符串用来在向服务器请求时发送 HTTP 头部中的 User-Agent 信息,有些服务器是需要检测这个信息的,如果没有设置User-Agent,那么服务器拒绝请求。设置后,可以骗过服务器对此的检查。
    1. CURLOPT_VERBOSE
      在使用该选项且第 3 个参数为 1 时,curl 库会显示详细的操作信息。这对程序的调试具有极大的帮助。
    1. CURLOPT_NOPROGRESS,CURLOPT_PROGRESSFUNCTION,CURLOPT_PROGRESSDATA
      这三个选项和跟数据传输进度相关。
      1)CURLOPT_PROGRESSFUNCTION设置回调函数,函数原型: int progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); progress_callback正常情况下每秒被libcurl调用一次。
      2)CURLOPT_NOPROGRESS必须被设置为false才会启用该功能,
      3)CURLOPT_PROGRESSDATA指定的参数将作为CURLOPT_PROGRESSFUNCTION指定函数的第一个参数。
    1. CURLOPT_TIMEOUT,CURLOPT_CONNECTIONTIMEOUT
      超时相关设置,时间单位为s
      1)CURLOPT_TIMEOUT设置整个libcurl传输超时时间。
      2)CURLOPT_CONNECTIONTIMEOUT
      设置连接等待时间。设置为0,则无限等待。
    1. CURLOPT_FOLLOWLOCATION,CURLOPT_MAXREDIRS
      重定向相关设置
      1)CURLOPT_FOLLOWLOCATION 设置为非0,响应头信息Location,即curl会自己处理302等重定向
      2)CURLOPT_MAXREDIRS指定HTTP重定向的最大次数
    1. CURLOPT_RANGE ,CURLOPT_RESUME_FROM/ CURLOPT_RESUME_FROM_LARGE 断点续传相关设置。
      1)CURLOPT_RANGE 指定char *参数传递给libcurl,用于指明http请求的range
      2)CURLOPT_RESUME_FROM传递一个long参数作为偏移量给libcurl,指定开始进行传输的位置。CURLOPT_RESUME_FROM大小限制为2G,超过可以使用CURLOPT_RESUME_FROM_LARGE
    1. CURLOPT_POSTFIELDS,CURLOPT_POSTFIELDSIZE
      1)CURLOPT_POSTFIELDS 传递一个作为HTTP “POST”操作的所有数据的字符串。
      2)CURLOPT_POSTFIELDSIZE 设置POST 字节大小。
    1. CURLOPT_NOBODY
      设置该属性即可告诉libcurl我想发起一个HEAD请求 有时候你想查询服务器某种资源的状态,比如某个文件的属性:修改时间,大小等等,但是并不需要具体得到该文件,这时我们仅需要HEAD请求。
    1. CURLOPT_ACCEPT_ENCODING
      设置libcurl对特定压缩方式自动解码,支持的方式有: “br, gzip, deflate”. 第3个参数为指定的压缩方式,如果设置为 " ",则表明三种都支持。
    1. CURLOPT_MAX_RECV_SPEED_LARGE,CURLOPT_MAX_SEND_SPEED_LARGE
      限速相关设置
      1)CURLOPT_MAX_RECV_SPEED_LARGE,指定下载过程中最大速度,单位bytes/s。
      2)CURLOPT_MAX_SEND_SPEED_LARG,指定上传过程中最大速度,单位bytes/s。
    1. CURLOPT_FORBID_REUSE ,CURLOPT_FRESH_CONNEC
      如果不使用长连接,需要设置这两个属性
      1)CURLOPT_FORBID_REUSE 设置为1,在完成交互以后强迫断开连接,不重用。
      2)CURLOPT_FRESH_CONNECT设置为1,强制获取一个新的连接,替代缓存中的连接。
    1. CURLOPT_NOSIGNAL
      当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。如果不设置这个选项,libcurl将会发信号打断这个wait从而可能导致程序crash。 在多线程处理场景下使用超时选项时,会忽略signals对应的处理函数。
    1. CURLOPT_BUFFERSIZE
      指定libcurl中接收缓冲区的首选大小(以字节为单位),但是不保证接收数据时每次数据量都能达到这个值。此缓冲区大小默认为CURL_MAX_WRITE_SIZE(16kB)。允许设置的最大缓冲区大小为CURL_MAX_READ_SIZE(512kB)。 允许设置的最小缓冲区大小为1024。

    DNS相关选项:

    1. CURLOPT_IPRESOLVE
      指定libcurl 域名解析模式。支持的选项有:
      1)CURL_IPRESOLVE_WHATEVER:默认值,相当于PF_UNSPEC,支持IPv4/v6,具体以哪个优先需要看libc底层实现,Android中默认以IPv6优先,当IPv6栈无法使用时,libcurl会用IPv4。
      2)CURL_IPRESOLVE_V4:.仅请求A记录,即只解析为IPv4地址。
      3)CURL_IPRESOLVE_V6:.仅请求AAAA记录,即只解析为IPv6地址。
      注意:该功能生效的前提是libcurl支持IPv6,需要在curl/lib/curl_config.h配置#define ENABLE_IPV6 1
    1. CURLOPT_DNS_CACHE_TIMEOUT
      设置libcurl DNS缓存超时时间,默认为60秒,即每60秒清一次libcurl自身保存的DNS缓存。
      如果设置为0,则不适用DNS缓存,设置为-1,则永远不清缓存。
    1. CURLOPT_DNS_USE_GLOBAL_CACHE
      让libcurl使用系统DNS缓存,默认情况下,libcurl使用本身的DNS缓存。

    这几个是较常用的选项,当然,libcurl远远不止这几个选项,更详细的使用方法可以参考官网。

    最后使用easy interface完成下载的简单代码:

    #include <stdio.h>
    #include <string.h>
    #include <curl/curl.h>
    #include <unistd.h>
    
    //#define CURL_DEBUG 1
    #define CURL_WAIT_TIMEOUT_MSECS 60000 //60s
    #define CURL_MULIT_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;
        
        //int
        FILE* save_file = fopen(filename,"w");
        if(save_file == NULL){
            printf("open save file fail!\n");
            return -1;
        }
    
        curl_handle = curl_easy_init();
        if(curl_handle){
            curl_easy_setopt(curl_handle, CURLOPT_URL, url);//set down load url
            curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, save_file);//set download file
            curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, recive_data_fun);//set call back fun
            curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, read_head_fun);//set call back fun
    #ifdef CURL_DEBUG
            curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1);
    #endif 
    
        //start down load
            res = 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(url){
            free(url);
        }
    
        return 0;
    }
    

    2、multi interface使用方法

    multi interface的使用是在easy interface的基础之上,将多个easy handler加入到一个stack中,同时发送请求。与easy interface不同,它是一种异步,非阻塞的传输方式。

    在掌握easy interface的基础上,multi interface的使用也很简单:
    1)curl_multi _init初始化一个multi handler对象,
    2)初始化多个easy handler对象,使用curl_easy_setopt进行相关设置,
    3)调用curl_multi _add_handle把easy handler添加到multi curl对象中
    4)添加完毕后执行curl_multi_perform方法进行并发的访问,
    5)访问结束后curl_multi_remove_handle移除相关easy curl对象,先用curl_easy_cleanup清除easy handler对象,最后curl_multi_cleanup清除multi handler对象。

    multi interface一些函数说明:
    1)和easy interface类似,multi 的初始化和清除函数如下:

     CURLM *curl_multi_init( );
     CURLMcode curl_multi_cleanup( CURLM*multi_handle );
    

    2)

    CURLMcode curl_multi_add_handle(CURLM *multi_handle, CURL *easy_handle);
    CURLMcode curl_multi_remove_handle(CURLM *multi_handle, CURL *easy_handle);
    

    当设置好easy模式并准备传输的时候,可以使用curl_multi_add_handle替代curl_easy_perform,这样easy handler则会加入multi栈中。我们能在任何时候增加一个esay handler给multi模式,即使easy已经在执行传输操作了。
    也可以在任何时候使用curl_multi_remove_handle将esay handler从multi栈中移出,一旦移出可以再次使用curl_easy_perform来进行传输任务。

    3)

    CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles);
    

    添加easy handler到multi并不马上开始执行,由curl_multi_perform启动执行。
    启动后将执行所有multi stack中的收发事件。如果栈上是空的直接返回。函数参数running_handles会返回当前还未结束的easy handler个数。

    4)等待及超时

    CURLMcode curl_multi_fdset(CURLM *multi_handle,
                               fd_set *read_fd_set,
                               fd_set *write_fd_set,
                               fd_set *exc_fd_set,
                               int *max_fd);
                               
    CURLMcode curl_multi_wait(CURLM *multi_handle,
                              struct curl_waitfd extra_fds[],
                              unsigned int extra_nfds,
                              int timeout_ms,
                              int *numfds);                           
    

    libcurl中,旧的API使用curl_multi_fdset设置 select或者poll模型触发。
    我们看下官网给的example:

    #ifdef _WIN32
    #define SHORT_SLEEP Sleep(100)
    #else
    #define SHORT_SLEEP usleep(100000)
    #endif
     
    fd_set fdread;
    fd_set fdwrite;
    fd_set fdexcep;
    int maxfd = -1;
     
    long curl_timeo;
     
    curl_multi_timeout(multi_handle, &curl_timeo);
    if(curl_timeo < 0)
      curl_timeo = 1000;
     
    timeout.tv_sec = curl_timeo / 1000;
    timeout.tv_usec = (curl_timeo % 1000) * 1000;
     
    FD_ZERO(&fdread);
    FD_ZERO(&fdwrite);
    FD_ZERO(&fdexcep);
     
    /* get file descriptors from the transfers */
    mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
     
    if(maxfd == -1) {
      SHORT_SLEEP;
      rc = 0;
    }
    else
      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
     
    switch(rc) {
    case -1:
      /* select error */
      break;
    case 0:
    default:
      /* timeout or readable/writable sockets */
      curl_multi_perform(multi_handle, &still_running);
      break;
    }
     
    /* if there are still transfers, loop! */
    

    新的API中,官网更推荐使用curl_multi_wait的方式来实现,实现方便,同时也可以避免select中file descriptors不能大于1024的问题。curl_multi_wait会轮询multi上的所有easy句柄,一直阻塞直到至少有一个被触发或者超时。
    如果multi句柄正因为网络延时而挂起,会有一个更短更精确的时间来代替我们自己设置的超时时间timeout_ms。
    curl_waitfd参数添加需要监听的socket。
    wait返回后,numfds返回被触发的事件数量,若为0表示超时或者没有事件等待。numfds的值包括multi栈上的和extra_fds新加的之和。

    看下官网的example:

    CURL *easy_handle;
    CURLM *multi_handle;
     
    /* add the individual easy handle */
    curl_multi_add_handle(multi_handle, easy_handle);
     
    do {
      CURLMcode mc;
      int numfds;
     
      mc = curl_multi_perform(multi_handle, &still_running);
     
      if(mc == CURLM_OK ) {
        /* wait for activity, timeout or "nothing" */
        mc = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);
      }
     
      if(mc != CURLM_OK) {
        fprintf(stderr, "curl_multi failed, code %d.n", mc);
        break;
      }
     
      /* 'numfds' being zero means either a timeout or no file descriptors to
         wait for. Try timeout on first occurrence, then assume no file
         descriptors and no file descriptors to wait for means wait for 100
         milliseconds. */
     
      if(!numfds) {
        repeats++; /* count number of repeated zero numfds */
        if(repeats > 1) {
          WAITMS(100); /* sleep 100 milliseconds */
        }
      }
      else
        repeats = 0;
     
    } while(still_running);
     
    curl_multi_remove_handle(multi_handle, easy_handle);
    

    对于select和curl_multi_wait两种方式,都可以使用curl_multi_timeout获取一个合适的超时时间,当然,超时时间也可以我们自己设置。

    5)

    CURLMsg *curl_multi_info_read( CURLM *multi_handle,   int *msgs_in_queue);
    

    我们可以调用curl_multi_info_read获取每一个执行完成的操作信息。在完成后即将其移除multi stack。

    /* call curl_multi_perform or curl_multi_socket_action first, then loop
       through and check if there are any transfers that have completed */
    struct CURLMsg *m;
    do {
      int msgq = 0;
      m = curl_multi_info_read(multi_handle, &msgq);
      if(m && (m->msg == CURLMSG_DONE)) {
        CURL *e = m->easy_handle;
        transfers--;
        curl_multi_remove_handle(multi_handle, e);
        curl_easy_cleanup(e);
      }
    } while(m);
    

    最后使用multi interface完成并发下载的简单代码:

    #include <stdio.h> 
    #include <string.h> 
    #include <curl/curl.h> 
    #include <unistd.h> 
     
    //#define CURL_DEBUG 1 
    #define CURL_WAIT_TIMEOUT_MSECS 1000 //1s 
    #define CURL_MULIT_MAX_NUM 5 
     
    typedef struct curl_obj{ 
        CURL* curl_handle; 
        FILE* save_file; 
        char* fetch_url; 
        size_t (*recive_data_fun)( void *ptr, size_t size, size_t nmemb, void *stream); 
        size_t (*read_head_fun)( void *ptr, size_t size, size_t nmemb, void *stream); 
    }curl_obj; 
     
    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("ERROR----arg1 is url; arg2 is out file\n"); 
            return -1; 
        } 
     
        char* outfile_name[CURL_MULIT_MAX_NUM] = {0}; 
        curl_obj obj[CURL_MULIT_MAX_NUM]; 
        int mulit_h_num = ((argc -1) < CURL_MULIT_MAX_NUM)? (argc -1):CURL_MULIT_MAX_NUM; 
         
        CURLM *multi_handle = curl_multi_init();     
        for(int i=0;i<mulit_h_num;i++){ 
            obj[i].fetch_url = strdup( argv[i+1]);//need free 
            char out_filename[1024] ; 
            sprintf(out_filename,"/storage/external_storage/sda4/%s",strrchr( argv[i+1], '/')); 
            printf("----save_file[%d] [%s]\n",i,out_filename); 
            obj[i].save_file = fopen(out_filename,"w"); 
            if(!obj[i].save_file){ 
                printf("ERROR----fail!!!\n"); 
                goto release; 
            } 
             
            obj[i].curl_handle = curl_easy_init(); 
            obj[i].recive_data_fun = recive_data_fun; 
            obj[i].read_head_fun = read_head_fun; 
            if(obj[i].curl_handle){ 
                curl_easy_setopt(obj[i].curl_handle, CURLOPT_NOSIGNAL, 1L);
                curl_easy_setopt(obj[i].curl_handle, CURLOPT_URL, obj[i].fetch_url);//set down load url 
                curl_easy_setopt(obj[i].curl_handle, CURLOPT_WRITEDATA, obj[i].save_file);//set download file 
                curl_easy_setopt(obj[i].curl_handle, CURLOPT_WRITEFUNCTION, obj[i].recive_data_fun);//set call back fun             
    #ifdef CURL_DEBUG 
                curl_easy_setopt(obj[i].curl_handle, CURLOPT_VERBOSE, 1); 
    #else 
                curl_easy_setopt(obj[i].curl_handle, CURLOPT_HEADERFUNCTION, obj[i].read_head_fun);//set call back fun 
    #endif  
                if(multi_handle) curl_multi_add_handle(multi_handle, obj[i].curl_handle);//add task 
            }else{ 
                printf("fetch [%s]----ERROR!!!\n",obj[i].fetch_url ); 
                //goto release; 
            } 
        } 
         
        int still_running,repeats;
        curl_multi_perform(multi_handle, &still_running); 
        do { 
            int numfds = 0; 
            long timeout_ms = CURL_WAIT_TIMEOUT_MSECS; 
            curl_multi_timeout(multi_handle, &timeout_ms);//get timeout ms instead 
            CURLMcode retcode = curl_multi_wait(multi_handle, NULL, 0, timeout_ms, &numfds); 
            if (retcode != CURLM_OK) { 
                printf("ERROR----curl_multi_wait  errorcode[%d]\n",retcode);           
                break; 
            } 
            /* 'numfds' being zero means either a timeout or no file descriptors to
               wait for. Try timeout on first occurrence, then assume no file
               descriptors and no file descriptors to wait for means wait for 10
               milliseconds. */
            if(!numfds) {
                if(repeats++ > 60){
                    printf("ERROR----timeout break!!! \n");           
                    break;
                }else{
                    usleep(10*1000);  /* sleep 10 milliseconds */
                    continue;
                }
            }
            else{
                repeats = 0;
            }
              
            retcode = curl_multi_perform(multi_handle, &still_running); 
            if (retcode != CURLM_OK) { 
                printf("ERROR----curl_multi_perform  errorcode[%d]\n",retcode); 
                break; 
            } 
            //printf("still_running[%d]\tnumfds[%d]\n",still_running,numfds );
    
            int msgs_left = 0; 
            CURLMsg *msg = NULL; 
            while ((msg = curl_multi_info_read(multi_handle, &msgs_left)) != NULL){ 
                if (msg->msg == CURLMSG_DONE) { 
                    long http_response_code = -1; 
                    char* http_url = NULL; 
                    curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &http_response_code); 
                    curl_easy_getinfo(msg->easy_handle, CURLINFO_EFFECTIVE_URL, &http_url);
                    printf("[%s]fetch done, response[%d]\n",http_url,http_response_code ); 
                } 
            } 
        } while (still_running); 
        
    release:  
         printf("release\n"); 
         for(int i=0;i<mulit_h_num;i++){ 
            if(obj[i].curl_handle){ 
                curl_multi_remove_handle(multi_handle, obj[i].curl_handle); 
                curl_easy_cleanup(obj[i].curl_handle); 
            } 
            if(obj[i].save_file){ 
                fclose(obj[i].save_file); 
                obj[i].save_file = NULL; 
            } 
            if(obj[i].fetch_url){ 
                free(obj[i].fetch_url); 
                obj[i].fetch_url = NULL; 
            } 
        } 
        if(multi_handle !=NULL){
            curl_multi_cleanup(multi_handle); 
        }
     
        return 0; 
    }
    
    展开全文
  • libcurl使用注意

    2020-12-01 15:42:02
    libcurl使用注意: 注意点1:现象:http短连接超过一定次数后一直返回错误7,即CURLE_COULDNT_CONNECT 过程有打印:Immediate connect fail for 114.116.228.34: Too many open files 使用netstat查看发现有大量的...
  • libcurl使用Https说明

    2014-08-07 11:57:39
    libcurl使用Https说明,使用此文档里面有资源。帮助开发基于SOCKET的HTTPS传输协议。(描述可能不详)
  • libcurl使用示例

    千次阅读 2014-04-30 10:49:54
    libcurl使用示例 简要说明:C++使用libcurl访问"www.baidu.com",获取返回码和打印出http文件 /* * @ libcurl使用示例 * @ 2014.04.29 * @ g++ -o LibCurlFunc LibCurlFunc.cpp -lcurl */
  • libcurl使用demo,根据一个网址,获取它的http头信息,然后解析其中的属性值
  • libcurl使用演示样例

    2016-03-22 20:03:00
    简要说明:C++使用libcurl訪问"www.baidu.com"。... /* * @ libcurl使用演示样例 * @ 2014.04.29 * @ g++ -o LibCurlFunc LibCurlFunc.cpp -lcurl */ #include <iostream> #include <string.h> #...
  • libcurl 使用心得

    2013-10-25 11:38:40
    1.libcurl使用writefunction来读取数据到内存,writefunction类似于socket的read,因此需要多次读取,每次都append上 2.多进程下请务必在主进程使用curl_global_init(),如果不这样做,每个线程会在curl_easy_ini()...
  • PHP libcurl使用总结

    千次阅读 2015-07-22 21:16:13
    PHP libcurl使用总结curl是利用URL语法在命令行方式下工作的开源文件传输工具,使用非常广泛。php也通过由 Daniel Stenberg开发的libcurl扩展库对curl提供支持。libcurl支持的协议很多,比如:http,https,ftp,gopher...
  • libcurl使用demo

    2017-06-20 14:20:15
    lib curl 实现http client示例
  • libcurl使用方法

    热门讨论 2010-04-13 15:52:49
    如何在vs中使用libcurl,完整的解说libcurl怎么在vs中编译以及怎么在别的工程中使用的帮助文档。对没有接触过libcurl使用者来说这个文档是非常有价值的。 libcurl官网:http://curl.haxx.se libcurl下载:...
  • 1.简单使用步骤及部分参数解释:...2. libcurl 使用的几个注意事项:https://blog.csdn.net/a_ran/article/details/40511903 3.curl设置超时相关:https://www.cnblogs.com/wainiwann/p/3494391.h...
  • libcurl使用心得libcurl使用心得

    千次阅读 2009-03-05 23:49:00
    Libcurl为一个免费开源的,客户端url传输库,支持FTP,FTPS,TFTP,HTTP,HTTPS,GOPHER,TELNET,DICT,FILE和LDAP,跨...并且易于使用。http://curl.haxx.se/libcurl/从http://curl.haxx.se/libcurl/下载一个稳定的版

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,278
精华内容 1,311
关键字:

libcurl使用