2012-12-16 41 views
10

मेरे पास होमवर्क है जहां मुझे दो HTTP प्रतिक्रियाओं की तुलना करने के लिए किसी भी तरह की आवश्यकता है। मैं इसे सी पर लिख रहा हूं और चीजों को आसान बनाने के लिए मैं libcurl का उपयोग करता हूं। मैं उस फ़ंक्शन को कॉल कर रहा हूं जो HTTP अनुरोध करने और किसी अन्य फ़ंक्शन से प्रतिक्रिया करने के लिए libcurl का उपयोग करता है, और मैं HTTP प्रतिक्रिया को char * के रूप में वापस करना चाहता हूं। यहाँ मेरी कोड अब तक (यह दुर्घटनाओं) है:सी में, आप स्ट्रिंग में HTTP प्रतिक्रिया पढ़ने के लिए libcurl का उपयोग कैसे करते हैं?

#include <stdio.h> 
#include <curl/curl.h> 
#include <string.h> 

size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) { 
    size_t written; 
    written = fwrite(ptr, size, nmemb, stream); 
    return written; 
} 

char *handle_url(void) { 
    CURL *curl; 
    char *fp; 
    CURLcode res; 
    char *url = "http://www.yahoo.com"; 
    curl = curl_easy_init(); 
    if (curl) { 
     curl_easy_setopt(curl, CURLOPT_URL, url); 
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); 
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); 
     res = curl_easy_perform(curl); 
     if(res != CURLE_OK) 
       fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); 

     curl_easy_cleanup(curl); 

     //printf("\n%s", fp); 
    } 
    return fp; 
} 

यह समाधान C libcurl get output into a string काम करता है, लेकिन नहीं मेरे मामले में, क्योंकि मैं तो बस बुला कार्य करने के लिए स्ट्रिंग वापस जाने के लिए चाहते हैं।

कोई विचार?

+0

'char * fp;' क्या है? आप इसे वापस क्यों कर रहे हैं? आप इसके लिए स्मृति आवंटित कैसे/कहां कर रहे हैं? मेरा चश्मा कहाँ हैं? –

+0

लॉल। मेरे पास सी लिखने के लिए सालों थे इसलिए मैं शून्य पर वापस आ गया हूं। बात यह है कि यह "सी libcurl एक स्ट्रिंग में आउटपुट प्राप्त करने में काम कर रहा है" उदाहरण मैं ऊपर refering कर रहा हूँ। मुझे सटीक डेटा इनपुट नहीं पता है इसलिए मुझे यकीन नहीं है कि char * fp के लिए स्मृति आवंटित करने पर काम करेगा। –

+0

आपका 'write_data' पैरामीटर के रूप में 'char * fp' पारित किया जाना चाहिए, लेकिन आपने इसे' फ़ाइल 'लेने के लिए परिभाषित किया है। साथ ही, आपको उस मामले को संभालने की आवश्यकता होगी जहां आपके 'write_func' को एक से अधिक बार बुलाया जाता है। अंत में, यदि आप उम्मीद करते हैं कि आप काम करना चाहते हैं, तो 'char * fp' को पॉइंटर पर पॉइंटर के रूप में' write_func() 'में पारित किया जाना है, ताकि आप इसे ठीक से आवंटित कर सकें। दूसरे शब्दों में, आपके 'write_func()' को 'char **' लेना चाहिए, न कि 'FILE *'। – mpontillo

उत्तर

18

यह आपके लिए तय किया गया है। आपको उस मामले को संभालने की आवश्यकता है जहां write_data() फ़ंक्शन को कई बार कहा जाता है, और इसे सही प्रकार का पैरामीटर पास करें। आपको यह भी ट्रैक रखना होगा कि आपको कितनी बड़ी संरचना मिली है, ताकि आप पर्याप्त मेमोरी आवंटित कर सकें।

फ़ंक्शन में मैंने printf को डीबग में छोड़ा ताकि यह समझने में सहायता के लिए कि यह कैसे काम करता है।

#include <stdio.h> 
#include <curl/curl.h> 
#include <string.h> 
#include <stdlib.h> 

struct url_data { 
    size_t size; 
    char* data; 
}; 

size_t write_data(void *ptr, size_t size, size_t nmemb, struct url_data *data) { 
    size_t index = data->size; 
    size_t n = (size * nmemb); 
    char* tmp; 

    data->size += (size * nmemb); 

#ifdef DEBUG 
    fprintf(stderr, "data at %p size=%ld nmemb=%ld\n", ptr, size, nmemb); 
#endif 
    tmp = realloc(data->data, data->size + 1); /* +1 for '\0' */ 

    if(tmp) { 
     data->data = tmp; 
    } else { 
     if(data->data) { 
      free(data->data); 
     } 
     fprintf(stderr, "Failed to allocate memory.\n"); 
     return 0; 
    } 

    memcpy((data->data + index), ptr, n); 
    data->data[data->size] = '\0'; 

    return size * nmemb; 
} 

char *handle_url(char* url) { 
    CURL *curl; 

    struct url_data data; 
    data.size = 0; 
    data.data = malloc(4096); /* reasonable size initial buffer */ 
    if(NULL == data.data) { 
     fprintf(stderr, "Failed to allocate memory.\n"); 
     return NULL; 
    } 

    data.data[0] = '\0'; 

    CURLcode res; 

    curl = curl_easy_init(); 
    if (curl) { 
     curl_easy_setopt(curl, CURLOPT_URL, url); 
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); 
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data); 
     res = curl_easy_perform(curl); 
     if(res != CURLE_OK) { 
       fprintf(stderr, "curl_easy_perform() failed: %s\n", 
         curl_easy_strerror(res)); 
     } 

     curl_easy_cleanup(curl); 

    } 
    return data.data; 
} 

int main(int argc, char* argv[]) { 
    char* data; 

    if(argc < 2) { 
     fprintf(stderr, "Must provide URL to fetch.\n"); 
     return 1; 
    } 
    data = handle_url(argv[1]); 

    if(data) { 
     printf("%s\n", data); 
     free(data); 
    } 

    return 0; 
} 

नोट: gcc -o test test.c -lcurl (यह मानते हुए आप test.c में चिपकाया) के साथ संकलन। परीक्षण printf() कॉल देखने के लिए gcc -o test test.c -lcurl -DDEBUG का उपयोग करें।

अस्वीकरण: यह बदसूरत, त्वरित और गंदे कोड है। बग हो सकता है। कृपया more robust, better commented example here देखें।

+0

धन्यवाद @ माइक, यह काम करता है !!! अब मुझे केवल याद रखना होगा (पढ़ना) कैसे आवंटित और malloc काम करता है। –

+1

बधाई हो, आपने getinmemory.c libcurl उदाहरण को फिर से कार्यान्वित किया है: http://curl.haxx.se/libcurl/c/getinmemory.html :-) –

+1

@ डैनियल, हां, लिंक के लिए धन्यवाद। वैसे भी पता लगाने के लिए यह एक मजेदार व्यायाम था। =) – mpontillo