Curl write callback doesn't get called for some handles
I just followed the curl multihandle example given in http://curl.haxx.se/libcurl/c/multi-single.html with the following modifications:
- I added 2 handles to the multihandle instead of one.
- I set the
CURLOPT_WRITEDATA
andCURLOPT_WRITEFUNCTION
options on both the handles.
The responses are supposed to go to the write callback function, and not to stdout. But when I run the program, for one curl handle, the response gets written to stdout, and for the other, the write callback function gets called. If you are interested below is my complete program. I'm not just trying to try out the examples, I face a similar problem in my real code (only it is worse there, for some curl handles response neither goes to stdout nor to callback), so it is important. Please help before I shoot myself. The cartridge is not empty.
#include <stdio.h>
#include <string>
#include<iostream>
/* somewhat unix-specific */
#include <sys/time.h>
#include <unistd.h>
/* curl stuff */
#include <curl/curl.h>
using namespace std;
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) //no ordering of responses against requests maintained yet.
{
cout << "\nwrite_data called with non 0 data with userp " << userp;
cout.flush();
string* stored_response = (string*)userp;
string chunk((char*)buffer,nmemb*size/sizeof(char));
stored_response->append(chunk);
return nmemb*size;
}
/*
* Simply download a HTTP file.
*/
int main(void)
{
CURL *http_handle;
CURLM *multi_handle;
int still_running; /* keep number of running handles */
http_handle = curl_easy_init();
string* response = new string("");
cout << "\nresponse pointer for yahoo.com=" << response;
cout.flush();
curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, response);
curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, write_data);
/* set the options (I left out a few, you'll get the point anyway) */
curl_easy_setopt(http_handle, CURLOPT_URL, "http://www.yahoo.com/");
/* init a multi stack */
multi_handle = curl_multi_init();
/* add the individual transfers */
curl_multi_add_handle(multi_handle, http_handle);
http_handle = curl_easy_init();
response = new string("");
cout << "\nresponse pointer for google.com=" << response;
cout.flush();
// curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, response);
// curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, write_data);
/* set the options (I left out a few, you'll get the point anyway) */
curl_easy_setopt(http_handle, CURLOPT_URL, "http://www.google.com/");
curl_multi_add_handle(multi_handle, http_handle);
/* we start some action by calling perform right away */
int multi_perform_ret;
do
{
multi_perform_ret = curl_multi_perform(multi_handle, &still_running);
}
while(multi_perform_ret == CURLM_CALL_MULTI_PERFORM);
while(still_running) {
cout << "\nstill_running=" << still_running;
cout.flush();
struct timeval timeout;
int rc; /* select() return code */
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
i开发者_如何转开发nt maxfd = -1;
long curl_timeo = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
/* set a suitable timeout to play around with */
/*
timeout.tv_sec = 1;
timeout.tv_usec = 0;
curl_multi_timeout(multi_handle, &curl_timeo);
if(curl_timeo >= 0) {
timeout.tv_sec = curl_timeo / 1000;
if(timeout.tv_sec > 1)
timeout.tv_sec = 1;
else
timeout.tv_usec = (curl_timeo % 1000) * 1000;
}
*/
/* get file descriptors from the transfers */
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
switch(rc) {
case -1:
/* select error */
still_running = 0;
printf("select() returns error, this is badness\n");
break;
case 0:
default:
/* timeout or readable/writable sockets */
do
{
multi_perform_ret = curl_multi_perform(multi_handle, &still_running);
}
while(multi_perform_ret == CURLM_CALL_MULTI_PERFORM);
break;
}
}
curl_multi_cleanup(multi_handle);
curl_easy_cleanup(http_handle);
return 0;
}
I am an idiot. I had commented out setting the callback for the 2nd curl handle.
精彩评论