在我的OS X应用程序中,我一直使用NSURLRequest将HTTP请求发送到服务器并接收响应。 现在我需要迁移此代码以使用libcurl,以便能够在Windows和Mac上运行它。
出于某种原因,我无法让它发挥作用......
这是我正在尝试做的事情:
当与请求一起发送的块有效时,“application / octet-stream”数据块立即被发送回请求应用程序。如果文件无效,则返回返回码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();
}
我的写函数看起来像这样:
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吗?
我很想听听你的想法!提前谢谢!
答案 0 :(得分:1)
您应该使用curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
传递自定义标头,而不是使用期望长参数的CURLOPT_HEADER
(0或1不包括/包含正文输出中的标头)。
答案 1 :(得分:0)
我发现的唯一问题是您没有保存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;
}