C语言 在 C 中,如何使用 libcurl 将 HTTP 响应读入字符串?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13905774/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:46:07  来源:igfitidea点击:

In C, how do you use libcurl to read a HTTP response into a string?

cstringlibcurlhttpresponse

提问by empty set

I have homework where I need somehow to compare two HTTP responses. I am writing it on C and I use libcurl to make things easier. I am calling the function that uses libcurl to do a HTTP request and response from another function, and I want to return the HTTP response as a char *. Here is my code so far (it crashes):

我有作业需要以某种方式比较两个 HTTP 响应。我在 C 上写它,我使用 libcurl 使事情变得更容易。我正在调用使用 libcurl 执行来自另一个函数的 HTTP 请求和响应的函数,并且我想将 HTTP 响应作为char *. 到目前为止,这是我的代码(它崩溃了):

#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;
}

This solution C libcurl get output into a stringworks, but not in my case because I just want to return the string to the calling function.

这个解决方案C libcurl get output into a string有效,但在我的情况下不是,因为我只想将字符串返回给调用函数。

Any ideas?

有任何想法吗?

回答by mpontillo

Fixed it for you. You need to handle the case where the write_data()function is called multiple times, and pass it the right kind of parameter. You also need to keep track of how big a structure you've got, so you can allocate enough memory.

给你修好了。您需要处理write_data()多次调用该函数的情况,并向其传递正确类型的参数。您还需要跟踪您拥有的结构有多大,以便分配足够的内存。

I left in a debug printfin the write_datafunction to help you understand how it works.

我在函数中进行了调试printfwrite_data以帮助您了解它是如何工作的。

#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 '##代码##' */

    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] = '##代码##';

    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] = '##代码##';

    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;
}

Note: compile with gcc -o test test.c -lcurl(assuming you pasted into test.c). Use gcc -o test test.c -lcurl -DDEBUGto see the test printf()calls.

注意:编译gcc -o test test.c -lcurl(假设您粘贴到test.c)。使用gcc -o test test.c -lcurl -DDEBUG查看测试printf()呼叫。

Disclaimer: this is ugly, quick-and-dirty code. There may be bugs. Please see the more robust, better commented example here.

免责声明:这是丑陋、快速和肮脏的代码。可能有bug。请在此处查看更强大、评论更好的示例