1

I'm performing a server request with curl in C++ which return responses in pieces and those pieces's size may also vary.

At the time of arrival of each piece, the callback function is being called. The problem is I can't detect when the connection finished in order to perform an another callback to my parent class.

And by the way, I want to know if we can set and detect timeout for a curl?

Here is my code in short:

CURL *curl = curl_easy_init();
curl_global_init(CURL_GLOBAL_ALL);

curl_easy_setopt(curl, CURLOPT_URL, "My URL");
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "My Postfields");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);

curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl_global_cleanup();

The default callback:

size_t writeCallback(char* buf, size_t size, size_t nmemb, void* up)
{
    //do something
    //But how can I detect the last callback when connection finished
    //in order to call an another one?
    return size*nmemb;
}
Thanh-Nhon Nguyen
  • 3,402
  • 3
  • 28
  • 41

1 Answers1

2

The data you want can be saved off during the callback, then used once curl_easy_perform returns. Example:

CURL *curl = curl_easy_init();
curl_global_init(CURL_GLOBAL_ALL);

// NOTE: added to accumulate data.
std::string result;

curl_easy_setopt(curl, CURLOPT_URL, "My URL");
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "My Postfields");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result); // NOTE: added
curl_easy_perform(curl);

// TODO: do something with your data stored in result

curl_easy_cleanup(curl);
curl_global_cleanup();

And in your write callback:

size_t writeCallback(char* buf, size_t size, size_t nmemb, void* up)
{
    std::string* pstr = static_cast<std::string*>(up);
    std::copy(buf, buf+size*nmemb, std::back_inserter(*pstr));
    return size*nmemb;
}

or something along those lines. I leave all the error checking to you (and sorry for any typos; I don't have a compiler to validate this on immediately available to me).

Regarding timeout length, there are a multitude of timeout options available to a easy-mode curl request. Too many to mention here, in fact. See the documentation for curl_easy_setopt, in particular the connection options approximately 2/3rd of the way down the page.

Best of luck.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • Thank you a lot! It solves the problem. The key here is CURLOPT_WRITEDATA, I didn't understand it well though. – Thanh-Nhon Nguyen Jun 13 '14 at 11:55
  • 1
    @NhonNguyen its a generic pointer that curl will take you you as an option (obviously) and pass *back* to you as a piece of goo during a call to your write-callback. We used the address of a local `std::string` object, which we then dereference and append all the data we just received to it. When the curl operation is complete, any data we received will be back in our string. – WhozCraig Jun 13 '14 at 12:11
  • I meant it was the CURLOPT_WRITEDATA that I didn't understand so that I got stuck. But when you gave me an example, I get it well! Thank you again for clarifying. It's very kind of you :) – Thanh-Nhon Nguyen Jun 13 '14 at 12:21