libcurl的使用(ftp-wildcard)——C++

libcurl的使用(ftp-wildcard)——C++,第1张

前言

之前未曾用过libcurl,只是在postman文档中见过http访问接口是通过libcurl实现的,这次看到同事用其实现的ftp,顿时觉得libcurl在通信中,还是挺万能的,所以我想学一下。

我查过资料后发现它真的支持很多协议:libcurl当前支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议。还有,它是一个跨平台的网络协议库,在基于LibCurl的程序里,主要采用callback function (回调函数)的形式完成传输任务,用户在启动传输前设置好各类参数和回调函数,当满足条件时libcurl将调用用户的回调函数实现特定功能。

学习libcurl,其实最好看一下官方的文档:libcurl - programming tutorial

基础知识介绍

libcurl有两种工作模式:easy interface,此模式是同步,阻塞式的传输,单个传输;

multi interface,此模式是在单个线程同时进行多个传输,它有多线程的优点,但是有不需要承担多线程管理的责任,很是方便。大家可根据不同的需求,选取不同的模式。

easy模式的流程
  • curl_global_init(long flags) :libcurl初始化,在任何平台使用libcurl的方法之前,必须要用此函数进行先初始化。唯一的参数是为了设置如何初始化的,有以下几个值:默认CURL_GLOBAL_DEFAULT是CURL_GLOBAL_ALL,即初始化所有已知的全部子模块;CURL_GLOBAL_WIN32,只能在windows系统上使用,它会初始化win32 socket ;CURL_GLOBAL_SSL,它会初始化ssl库。
#define CURL_GLOBAL_SSL (1<<0)
#define CURL_GLOBAL_WIN32 (1<<1)
#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL
  •  获取 *** 作句柄。根据自己的需求,选用不同的模式,获取对应的句柄。
m_pHndCurlEasy = curl_easy_init();
  • 传输时,通过curl_easy_setopt设置基本参数,如url地址、http头、cookie信息、发送超时时间等,其中,CURLOPT_URL是必设的选项,格式如下。 第二个参数不同值决定设置不同的参数类型,具体可参考博客:curl库中curl_easy_setopt函数详解_I_O_fly的博客-CSDN博客_curl_easy_setopt
curl_easy_setopt(handle, CURLOPT_URL, "http://domain.com/");
  • 设置完成后,调用curl_easy_perform(CURL *curl)函数发送数据我理解为“开始表演了!!”:基本配置已配置好,开始运转了
  • 数据发送完毕后,调用curl_easy_cleanup清空句柄
  • 不再使用libcurl后,调用curl_global_cleanup()做清理工作。也可以说一个curl_global_init对应一个curl_global_cleanup。
官方示例

官方示例的网址是:libcurl - source code examples

可以将官方示例下载下来,看看在各种场合的用法。

这里我贴一个ftp通配符下载文件的示例(ftp-wildcard),可以看出与我上方介绍的流程是一致的(easy模式)。

/* 
 * FTP wildcard pattern matching
 * 
 */
#include 
#include 

struct callback_data {
  FILE *output;
};

static long file_is_coming(struct curl_fileinfo *finfo,
                           struct callback_data *data,
                           int remains);

static long file_is_downloaded(struct callback_data *data);

static size_t write_it(char *buff, size_t size, size_t nmemb,
                       void *cb_data);

int main(int argc, char **argv)
{
  /* curl easy handle */
  CURL *handle;

  /* help data */
  struct callback_data data = { 0 };

  /* global initialization */
  int rc = curl_global_init(CURL_GLOBAL_ALL);
  if(rc)
    return rc;

  /* initialization of easy handle */
  handle = curl_easy_init();
  if(!handle) {
    curl_global_cleanup();
    return CURLE_OUT_OF_MEMORY;
  }

  /* turn on wildcard matching */
  curl_easy_setopt(handle, CURLOPT_WILDCARDMATCH, 1L);

  /* callback is called before download of concrete file started */
  curl_easy_setopt(handle, CURLOPT_CHUNK_BGN_FUNCTION, file_is_coming);

  /* callback is called after data from the file have been transferred */
  curl_easy_setopt(handle, CURLOPT_CHUNK_END_FUNCTION, file_is_downloaded);

  /* this callback will write contents into files */
  curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_it);

  /* put transfer data into callbacks */
  curl_easy_setopt(handle, CURLOPT_CHUNK_DATA, &data);
  curl_easy_setopt(handle, CURLOPT_WRITEDATA, &data);

  /* curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L); */

  /* set an URL containing wildcard pattern (only in the last part) */
  if(argc == 2)
    curl_easy_setopt(handle, CURLOPT_URL, argv[1]);
  else
    curl_easy_setopt(handle, CURLOPT_URL, "ftp://example.com/test/*");

  /* and start transfer! */
  rc = curl_easy_perform(handle);

  curl_easy_cleanup(handle);
  curl_global_cleanup();
  return rc;
}

static long file_is_coming(struct curl_fileinfo *finfo,
                           struct callback_data *data,
                           int remains)
{
  printf("%3d %40s %10luB ", remains, finfo->filename,
         (unsigned long)finfo->size);

  switch(finfo->filetype) {
  case CURLFILETYPE_DIRECTORY:
    printf(" DIR\n");
    break;
  case CURLFILETYPE_FILE:
    printf("FILE ");
    break;
  default:
    printf("OTHER\n");
    break;
  }

  if(finfo->filetype == CURLFILETYPE_FILE) {
    /* do not transfer files >= 50B */
    if(finfo->size > 50) {
      printf("SKIPPED\n");
      return CURL_CHUNK_BGN_FUNC_SKIP;
    }

    data->output = fopen(finfo->filename, "wb");
    if(!data->output) {
      return CURL_CHUNK_BGN_FUNC_FAIL;
    }
  }

  return CURL_CHUNK_BGN_FUNC_OK;
}

static long file_is_downloaded(struct callback_data *data)
{
  if(data->output) {
    printf("DOWNLOADED\n");
    fclose(data->output);
    data->output = 0x0;
  }
  return CURL_CHUNK_END_FUNC_OK;
}

static size_t write_it(char *buff, size_t size, size_t nmemb,
                       void *cb_data)
{
  struct callback_data *data = cb_data;
  size_t written = 0;
  if(data->output)
    written = fwrite(buff, size, nmemb, data->output);
  else
    /* listing output */
    written = fwrite(buff, size, nmemb, stdout);
  return written;
}

结束语

easy interface是基本的,也是最简单的用法,后续如果有空的话,写一篇multi interface的。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1353711.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-14
下一篇 2022-06-14

发表评论

登录后才能评论

评论列表(0条)

保存