libcurl库的使用的

libcurl库的使用的一些心得
一、概述

测试做一个下载工具,最开始想到了libcurl库,和它提供的一些接口。

二、libcurl提供的一些api的使用
1、CURLcode curl_global_init(long flags);----全局初始化函数,在windows下使用CURL_GLOBAL_WIN32,初始化win sock的一些信息。
2、CURL *curl_easy_init();-----初始化一个CURL*的句柄。
3、CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);----设置http的一些属性,设置给libcurl
4、CURLM *curl_multi_init(void);------初始化一个CURLM * 句柄,使用这个可以实现非阻塞模式,建议使用该函数
5、CURLMcode curl_multi_add_handle(CURLM *multi_handle,   CURL *curl_handle);----把CURL*句柄添加到CURLM * 中
6、CURLcode curl_easy_perform(CURL *curl);----执行下载或者上传任务,执行的是函数curl_easy_setopt设置的一些选项
7、CURLMcode curl_multi_perform(CURLM *multi_handle,  int *running_handles);-----执行下载或者上传任务,通过curl_multi_add_handle加入到CURLM*句柄中的各个任务。主要使用的是select非阻塞模式,通过这个可以比较容易的实现多线程任务。
8、void curl_easy_cleanup(CURL *curl);----清理CURL*句柄。
9、CURLMcode curl_multi_cleanup(CURLM *multi_handle);----清理CURLM*句柄。
10、void curl_global_cleanup(void);----清理全局初始化的堆栈操作。
注:最好看官网提供的一些英文资料和它提供的一些例子,这些东西比在网上随便找的资料有用的多。

三、设计思想。
1、对于一些大文件,创建一些线程去执行下载任务。----- 最主要的就是如何让各个线程从指定位置开始下载和到指定位置停止下载的问题。
2、如何实现下载,可以通过curl_easy_setopt函数设置一个回调函数完成对本地文件的写入,完成下载工作。---下载或其他任务,会在curl_easy_perform或curl_multi_perform函数调用后执行。
3、对于大文件,获取到http(或其他服务器)上的文件大小后,根据需要创建的线程数,给每个线程分配固定的数据段进行下载。
4、等各个文件分块下载完成后,把下载的文件块拼装起来,组合成需要的下载文件。----完成所有下载工作(这部分工作应该是最简单的)。

四、一些代码实例
1、从http头获取到下载文件的大小(我在网上没有找到实例)

/*
* get file size from http head data
*/
size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
  int r;
  long len = 0;


  /* _snscanf() is Win32 specific */
  // r = _snscanf(ptr, size * nmemb, "Content-Length: %ld\n", &len);
  r = sscanf((const char*)ptr, "Content-Length: %ld\n", &len);
  if (r) /* Microsoft: we don't read the specs */
    *((long *) stream) = len;


  return size * nmemb;
}

size_t write_func(void* , size_t , size_t , void* )
{
  return 0;
}

int32 getdownloadfilesize(const char* url)
{
#if WIN32
  curl_global_init(CURL_GLOBAL_WIN32);
#else
  curl_global_init(CURL_GLOBAL_ALL);
#endif


  CURL* hcurl = curl_easy_init();
  curl_easy_setopt(hcurl, CURLOPT_URL, url);


  curl_easy_setopt(hcurl, CURLOPT_FOLLOWLOCATION, 1L);        // 重定向
  curl_easy_setopt(hcurl, CURLOPT_CONNECTTIMEOUT, TIME_OUT);  // set connect timeout


  long filesize = 0;


  /* set http head call back function */
  curl_easy_setopt(hcurl, CURLOPT_HEADERFUNCTION, getcontentlengthfunc);
  curl_easy_setopt(hcurl, CURLOPT_HEADERDATA, &filesize);


  FILE* fp = fopen("test.txt", "ab+");
  if(!fp)
    return 0;


  curl_easy_setopt(hcurl, CURLOPT_WRITEDATA, fp);
  curl_easy_setopt(hcurl, CURLOPT_WRITEFUNCTION, write_func);


  curl_easy_perform(hcurl); // 函数会执行失败哦,不过没关系,我们已经从得到了filesize的大小了。


  fclose(fp);
  system("if exist test.txt del test.txt");

  // 清理工作
  curl_easy_cleanup(hcurl);
  curl_global_cleanup();


  return (int32)filesize;
}

2、设置断点续传。
void setcurlopt()
{
  curl_off_t local_file_len = -1 ;
  struct stat file_info;


  bool flag = false;
  //  g_loopsize是分段的大小
  curl_off_t nbeginsize = (nthreadcode - 1) * g_loopsize;


  /* get local file size */
  if(stat(m_strfile.c_str(), &file_info) == 0)
  {
    local_file_len =  file_info.st_size;
    nbeginsize += (int32)local_file_len;
    flag = true;
  }

  /* open file use append model */
  FILE* fp = fopen(m_strfile.c_str(), "ab+");
  if (fp == NULL) {
    perror(NULL);
    return;
  }

 /*
   *把需要文件开始下载的位置传给libcurl,多线程分段也主要
   * 是通过该函数设置下载部分,这里的参数类型必须为curl_off_t ,否则会得不到http的相应
  */
  curl_easy_setopt(m_hcurl, CURLOPT_RESUME_FROM_LARGE, flag?local_file_len,0);

  // 把文件指针传给libcurl,用户可以根据需求自己设计回调和需要传递的指针 
  SDownloadFile* file = xxx;
  curl_easy_setopt(m_hcurl, CURLOPT_WRITEDATA,  file);
  // 设置回调函数,writefunc是一个特殊的回调函数,我用多线程分段下载的 
  curl_easy_setopt(m_hcurl, CURLOPT_WRITEFUNCTION, wirtefunc);
 }

/*
* save the downloaded data to defined file
* 这里特别说明一下,分段去调用最后可能出现一个错误信息:failed write body(xxx!=xxxx)
* 这个可以忽略,具体请查看libcurl源码部分。
*/
size_t wirtefunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
  SDownloadFile* pinfo = (SDownloadFile*)stream;
  assert(pinfo);
  if(NULL == pinfo)
    return 0;

  uint32 ret = 0;
  int32 nLave = pinfo->nBeginLen + size * nmemb - pinfo->nEndLen;
  if(nLave > 0) // one part download success
  {
    fflush(pinfo->fp);
    fwrite(ptr, size, pinfo->nEndLen - pinfo->nBeginLen, pinfo->fp);
    fflush(pinfo->fp);


    pinfo->nBeginLen = pinfo->nEndLen;
  }
  else
  {
    assert(pinfo->nBeginLen + size * nmemb < (uint32)pinfo->nEndLen);
    ret = fwrite(ptr, size, nmemb, pinfo->fp);
    pinfo->nBeginLen += ret;
  }


  return ret;
}

typedef struct _SDownloadFile
{
  FILE*     fp;
  string    strfilename;
  int32     nBeginLen;
  int32     nEndLen;
  int32     ncode;
}SDownloadFile;

typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
typedef signed int int32;
typedef unsigned int uint32;
typedef signed long long int64;
typedef unsigned long long uint64;

3、关于文件组合。
把各个部分已二进制方式读出来,然后写入到一个新的文件中,并删除那些下载的部分文件。

-

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
libcurl是一个功能强大的,可用于执行各种网络操作的C语言。它支持多种协议,例如HTTP、FTP、SMTP等,并提供了各种选项和参数,以便您可以自定义网络请求以及如何处理响应。下面是一些使用libcurl的基本步骤: 1. 包含libcurl头文件 在您的C文件中,您需要包含libcurl的头文件: ```c #include <curl/curl.h> ``` 2. 初始化CURL 在使用libcurl之前,您需要初始化一个CURL句柄,可以使用`curl_easy_init()`函数来实现: ```c CURL *curl; curl = curl_easy_init(); if (!curl) { // 初始化失败 } ``` 3. 设置URL和选项 在CURL句柄上设置选项,以指定要执行哪个URL以及如何处理响应。例如,您可以使用`CURLOPT_URL`选项指定要访问的URL: ```c curl_easy_setopt(curl, CURLOPT_URL, "http://example.com"); ``` 还有许多其他选项可以设置,例如`CURLOPT_FOLLOWLOCATION`选项可以让libcurl自动跟踪重定向: ```c curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); ``` 4. 执行HTTP请求 一旦您设置了所有选项,就可以使用`curl_easy_perform()`函数执行HTTP请求: ```c CURLcode res; res = curl_easy_perform(curl); if (res != CURLE_OK) { // 请求失败 } ``` 5. 处理响应 处理HTTP响应的方式取决于您正在执行的操作。例如,如果您正在下载文件,您可以将响应写入本地文件: ```c FILE *fp; fp = fopen("myfile.txt", "wb"); curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); res = curl_easy_perform(curl); fclose(fp); ``` 如果您正在执行POST请求,则可以使用`CURLOPT_POSTFIELDS`选项设置请求正文,并使用`CURLOPT_WRITEFUNCTION`选项指定一个回调函数来处理响应: ```c curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "param1=value1&param2=value2"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); ``` 6. 清理 最后,清理CURL句柄并释放所有资源: ```c curl_easy_cleanup(curl); ``` 以上是使用libcurl的基本步骤。根据您的需求,您可以使用更多选项和参数自定义您的网络请求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LCS-312

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值