2021年4月24日 星期六

Libcurl 的使用範例

/* 
 * 這個例子說明如何寫Libcurl中的Callback 程式,這Callback將把 URL回傳的資料,放到記憶體當中。
 * Shows how the write callback function can be used to download data into a
 * chunk of memory instead of storing it in a file.
 * 
 */ 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include <curl/curl.h>
 
struct MemoryStruct {
  char *memory;
  size_t size;
};
/*
  這個例子的就是存取一個URL,傳回內容與CONTENT SIZE。
    
  size_t callback_function( void *ptr, size_t size, size_t nmemb, void *stream);
  這函數將在libcurl接收到數據後被調用,用來儲存http送回的資料。
  程式在處理回傳資料最難的就是不知道回傳的資料量有多少? 所以記憶體也不知道要需告多大。所以就設計了這個Callback。
  *ptr 是一快記憶體空間,裡面放著 http 傳回的資訊。
  size :說明 Contents 所指到的記憶體有多大?
  memb :這是一個有趣的參數,因為網路上每個字的單位有多大? 所以利用這個變數來做通知 Callback。實際的記憶體SIZE = size * memb
    userp:這個參數主要回傳一個應用程式可以使用的資料結構,
            struct MemoryStruct {
            char *memory;
            size_t size;
            };
    *memory 之中放著由 ptr 送進來的 HTTP 回傳的資料。
    size 是 memory 的 SIZER。
    CURLOPT_WRITEDATA用於表明CURLOPT_WRITEFUNCTION函數中的stream指針的來源。
    如果你沒有通過CURLOPT_WRITEFUNCTION屬性给easy handle設置回調函數,libcurl會提供一個預設的回調函數,它只是簡單的將接收到的數據印到標准輸出。
    你也可以通過 CURLOPT_WRITEDATA屬性之中的Callback,將資訊寫到記憶體之中,傳給Libcurl,然後透過 HTTP傳送出去。
*/
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);
 
    /* 
        將curl Library進行初始化,init the curl session 
    */
    curl_handle = curl_easy_init();
 
    /* 
        設定要存取的URL 
    */
    curl_easy_setopt(curl_handle, CURLOPT_URL, "https://www.example.com/");
 
    /* send all data to this function  */ 
    
    curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
 
    /* 
       we pass our 'chunk' struct to the callback function
       chunk 就會傳給 WriteMemoryCallback 之中的第四個參數 userp 
    */
    
    curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
 
    /* 
       這一行如果不寫,有時有問題,有的SERVER會有問題,所以務必要寫
    */ 
    curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
 
    /* get it down ! */ 
    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;
}

沒有留言:

張貼留言