【问题标题】:libcurl retrieve response from HTTP requestlibcurl 从 HTTP 请求中检索响应
【发布时间】:2013-11-13 21:29:49
【问题描述】:

在我的 OS X 应用程序中,我一直在使用 NSURLRequest 向服务器发送 HTTP 请求并接收响应。 现在我需要迁移此代码以使用 libcurl,以便能够在 Windows 和 Mac 上运行它。

由于某种原因,我无法让它工作......

这是我想要做的:

  • 使用 HTTP post 向服务器发送块
  • 服务器评估块并返回响应
  • 接收响应、评估、处理 ...

当与请求一起发送的块有效时,会立即将“应用程序/八位字节流”数据块发送回请求应用程序。如果文件无效,则返回返回码 403。

当我尝试将发布请求 URL 和数据块直接放在浏览器中时,它可以工作。 如果数据块有效,则下载一个文件,如果不是:显示403页面。

我的 libcurl 代码如下所示:

curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();

if (curl)
{
    struct url_data data;
    data.size = 0;
    data.data = (char*) malloc(4096); /* reasonable size initial buffer */

    if(NULL == data.data)
    {
        fprintf(stderr, "Failed to allocate memory.\n");
        return NULL;
    }

    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    curl_easy_setopt(curl, CURLOPT_URL, "<my-url>");
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, [postData cStringUsingEncoding:NSASCIIStringEncoding]);

    curl_slist_append(headerlist, "Content-Type: application/x-www-form-urlencoded");
    curl_slist_append(headerlist, [length cStringUsingEncoding:NSASCIIStringEncoding]);

    curl_easy_setopt(curl, CURLOPT_HEADER, headerlist);

    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);

    curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");

    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);
    }
    curl_global_cleanup();
}

而我的 write 函数是这样的:

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

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

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

    return size * nmemb;
}

我收到了正确的返回码以及 403 页面,以防该块无效。如果它有效,我没有收到响应块。永远不会调用 write 函数。连接总是立即关闭。

谁能告诉我我做错了什么?

这是libcurl的部分日志输出:

* Adding handle: conn: 0x2a9ee00
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x2a9ee00) send_pipe: 1, recv_pipe: 0
* About to connect() to <my-url> port 80 (#0)
*   Trying <my-url-ip>...
* Connected to <my-url> (<my-url-ip>) port 80 (#0)

recv-pipe 是否会导致问题? 应该是 1 吗?

我很想听听你的想法!提前致谢!

【问题讨论】:

  • 请展示你的写功能。
  • @jaeheung 更新了问题,谢谢。

标签: c http-post libcurl


【解决方案1】:

您应该使用 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); 传递您的自定义标头,而不是使用需要 long as 参数的 CURLOPT_HEADER(0 或 1 表示在正文输出中不包含/包含标头)。

【讨论】:

    【解决方案2】:

    我发现的唯一问题是您没有保存来自realloc() 的新地址。它肯定会崩溃,但 write_data() 应该至少被调用一次。

    你怎么知道它永远不会被调用?

    请改用write_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);
    
        fprintf(stderr, "data at %p size=%ld nmemb=%ld\n", ptr, size, nmemb);
        tmp = (char*) realloc(data->data, data->size + 1); /* +1 for '\0' */
        if (tmp == NULL) {
            fputs("Error (re)allocating memory", stderr);
            return 0;
        }
        data->data = tmp;
    
        memcpy((data->data + index), ptr, n);
        data->data[data->size] = '\0';
    
        return size * nmemb;
    }
    

    【讨论】:

    • 我并没有真正关心 write_data 函数,因为它甚至没有被调用。我怀疑这是这里的错误。我宁愿认为服务器响应时间过长,同时连接已关闭。
    • @guitarflow 您可以尝试设置 CURLOPT_TIMEOUT,但 libcurl 手册说“默认超时为 0(零),这意味着它永远不会超时。”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多