设置的时候,如果对curl获取的数据调用回调进行处理的话,需要以下两个设置

1、curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
2、curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);    

下面详细说明
.

一、CURLOPT_WRITEFUNCTION

#include <curl/curl.h>
 
size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);
 
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEFUNCTION, write_callback);

在CURLOPT_WRITEFUNCTION设置属性下,使用回调write_callback进行处理

一旦收到需要保存的数据,libcurl就会调用此回调函数。
对于大多数传输,此回调被多次调用,每次调用都会传递另一块数据。
*默认情况下数据输出到标准输出,fwrite是默认回调

ptr指向传递的数据,该数据的大小为nmemb ; size总是1。

官网 https://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html

.

二、CURLOPT_WRITEDATA

#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEDATA, void *pointer);

该选项下,将要传输的数据指针传递给 写回调函数,

如果使用 CURLOPT_WRITEFUNCTION 选项,这个 void *pointer 将会传递给回调函数的第四个参数 void *userdata

如果不使用 CURLOPT_WRITEFUNCTION 选项,则此处必须要是个文件类型的指针 ‘FILE *’ (cast to ‘void *’) ,用来默认情况传递个标准输出,也就是 fwrite(3)
( By default, this is a FILE * to stdout.)

官网 https://curl.haxx.se/libcurl/c/CURLOPT_WRITEDATA.html

.

三、官网示例

https://curl.haxx.se/libcurl/c/getinmemory.html

//getinmemory.c

 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include <curl/curl.h>
 
struct MemoryStruct {
  char *memory;
  size_t size;
};
 
static size_t
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
  size_t realsize = size * nmemb;
  struct MemoryStruct *mem = (struct MemoryStruct *)userp;
 
 // 注意这里根据每次被调用获得的数据重新动态分配缓存区的大小
  char *ptr = realloc(mem->memory, mem->size + realsize + 1); 
  if(ptr == NULL) {
    /* out of memory! */ 
    printf("not enough memory (realloc returned NULL)\n");
    return 0;
  }
 
  mem->memory = ptr;
  memcpy(&(mem->memory[mem->size]), contents, realsize);
  mem->size += realsize;
  mem->memory[mem->size] = 0;
 
  return realsize;
}
 
int main(void)
{
  CURL *curl_handle;
  CURLcode res;
 
  struct MemoryStruct chunk;
 
  chunk.memory = malloc(1);  /* will be grown as needed by the realloc above */ 
  chunk.size = 0;    /* no data at this point */ 
 
  curl_global_init(CURL_GLOBAL_ALL);
 
  /* init the curl session */ 
  curl_handle = curl_easy_init();
 
  /* specify URL to get */ 
  curl_easy_setopt(curl_handle, CURLOPT_URL, "https://www.example.com/");
 
  /* send all data to this function  */ 
  //对于同一次阻塞的curl_easy_perform而言,在写完获取的数据之前,会多次调用 WriteMemoryCallback
  curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
  
 
  /* we pass our 'chunk' struct to the callback function */ 
  curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
 
  /* some servers don't like requests that are made without a user-agent   field, so we provide one */ 
  curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
 
  /* get it! */ 
  //对于同一次阻塞的curl_easy_perform而言,在写完获取的数据之前,会多次调用 WriteMemoryCallback
  res = curl_easy_perform(curl_handle);
 
  /* check for errors */ 
  if(res != CURLE_OK) {
    fprintf(stderr, "curl_easy_perform() failed: %s\n",
            curl_easy_strerror(res));
  }
  else {
    /*
     * Now, our chunk.memory points to a memory block that is chunk.size
     * bytes big and contains the remote file.
     *
     * Do something nice with it!
     */ 
 
    printf("%lu bytes retrieved\n", (unsigned long)chunk.size);
  }
 
  /* cleanup curl stuff */ 
  curl_easy_cleanup(curl_handle);
 
  free(chunk.memory);
 
  /* we're done with libcurl, so clean it up */ 
  curl_global_cleanup();
 
  return 0;
}
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐