I have never done anything multithreaded or asynchronous in C ++, I used cURL only to execute synchronous requests.
To better visualize what I'm trying to do, I wrote a simple Javascript that will do what I want to do with cURL in C ++.
function AddRequest( method, url, data, id ) {
var httpObj = new ActiveXObject("Msxml2.XMLHTTP.6.0");
httpObj.onreadystatechange = function() {
if (httpObj.readyState == 4)
ResponseCallback( httpObj, id );
};
httpObj.Open( method, url, true );
httpObj.Send( data );
}
function ResponseCallback( httpObj, id ) {
WScript.Echo( id );
WScript.Echo( httpObj.ResponseText );
}
AddRequest("GET","http://example.com/","",1);
AddRequest("GET","https://www.facebook.com","",2);
WScript.Echo( "all requests sent" );
CURL just seems TOTALLY different and unnecessary more complicated than XmlHttpRequest, although both just send http requests ...
Here is my first approach (based on hogren's answer):
#include "stdafx.hpp"
#include <iostream> //#include <stdio.h>
#include <curl.h>
#include <pthread.h>
#include <map>
#include <string>
using namespace std;
bool printing = false;
struct requestStruct {
int id;
const char* url;
const char* method;
const char* body;
map<const char*, const char*> headers;
const char* proxy;
int timeout;
};
struct responseStruct {
long statusCode;
const char* body;
};
size_t writeToString(void *ptr, size_t size, size_t count, void *stream) {
((string*)stream)->append((char*)ptr, 0, size* count);
return size* count;
}
static void *ResponseCallback(int id, struct responseStruct *response) {
long statusCode = response -> statusCode;
const char* body = response -> body;
printing = true;
cout << id << " response received! Code: " << statusCode << endl << body << endl;
printing = false;
return NULL;
}
struct responseStruct HttpRequest(const char* url, const char* method, const char* body, map<const char*, const char*> &headers, const char* proxy, long timeout) {
CURL *curl;
curl = curl_easy_init();
long statusCode = 0;
map<const char*, const char*> respHeaders;
string respBody;
string _url(url);
string _method(method);
string _proxy(proxy);
struct curl_slist *headerList = NULL;
string headerString;
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
for (auto header=headers.begin(); header!=headers.end(); ++header) {
headerString = header->first;
headerString.append(": ").append(header->second);
headerList = curl_slist_append(headerList, headerString.c_str());
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerList);
if (_method == "POST" || _method == "PUT" || _method == "DELETE")
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
if (_url.find(string("https://")) != string::npos)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
if (_proxy != "")
curl_easy_setopt(curl, CURLOPT_PROXY, proxy);
if (timeout != 0)
curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeToString);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &respBody);
curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &statusCode);
struct responseStruct response;
response.statusCode = statusCode;
response.body = respBody.c_str();
curl_easy_cleanup(curl);
return response;
}
static void *AddRequest( void *arguments ) {
struct requestStruct *args = (struct requestStruct*)arguments;
int id = args->id;
const char* url = args->url;
const char* method = args->method;
const char* body = args->body;
map<const char*, const char*> headers = args->headers;
const char* proxy = args->proxy;
int timeout = args->timeout;
struct responseStruct response = HttpRequest(url, method, body, headers, proxy, timeout);
ResponseCallback(id,&response);
pthread_exit(0);
return NULL;
}
int main() {
pthread_t threads[3];
struct requestStruct reqArguments[3];
map<const char*, const char*> headers;
headers["User-Agent"] = "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0";
const char* proxy = "";
reqArguments[0].id = 0;
reqArguments[0].url = "https://www.facebook.com/";
reqArguments[0].method = "GET";
reqArguments[0].headers = headers;
reqArguments[0].body = "";
reqArguments[0].proxy = proxy;
reqArguments[0].timeout = 6000;
pthread_create(&threads[0], NULL, &AddRequest, (void *)&reqArguments[0]);
reqArguments[1].id = 1;
reqArguments[1].url = "https://www.facebook.com/";
reqArguments[1].method = "GET";
reqArguments[1].headers = headers;
reqArguments[1].body = "";
reqArguments[1].proxy = proxy;
reqArguments[1].timeout = 6000;
pthread_create(&threads[1], NULL, &AddRequest, (void *)&reqArguments[1]);
reqArguments[2].id = 2;
reqArguments[2].url = "https://www.facebook.com/";
reqArguments[2].method = "GET";
reqArguments[2].headers = headers;
reqArguments[2].body = "";
reqArguments[2].proxy = proxy;
reqArguments[2].timeout = 6000;
pthread_create(&threads[2], NULL, &AddRequest, (void *)&reqArguments[2]);
getchar();
return 0;
}
, .
:
1. - , .
4 , , , , .
2. HttpRequest() html, .
, 2 HttpRequest(), .:(
3. , , .
Btw: Visual ++ 2010, http Fiddler.