I am currently using the multi interface API of the libcurl library to send multiple HTTP requests without blocking. My current problem is that I can't send a HTTP request.
For some reason maxfd is always -1 which result in rc always being 0. So when the code get to the switch statement it always print "timeout" because rc is always 0.
I never used the mulit interface before but I used the easy interface a couple of time. Much of the code is very similar to this.
ReqestHandler.cpp
void RequestHandler::add(lua_State* lua, const std::string& url, const std::string& data) {
Request request;
CURL* curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "RoBot/ Version 1");
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 0);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &request.response);
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &request.headers);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &request.code);
if (!data.empty()) {
curl_easy_setopt(curl, CURLOPT_POST, true);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, data.size());
}
request.curl = curl;
request.lua = lua;
curl_multi_add_handle(_curlm, curl);
_requests.push_back(request);
}
void RequestHandler::tick() {
if (!_requests.empty()) {
curl_multi_perform(_curlm, &_isRunning);
do {
struct timeval timeout;
int rc;
CURLMcode mc;
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd = -1;
long curl_timeo = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
curl_multi_timeout(_curlm, &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;
}
}
mc = curl_multi_fdset(_curlm, &fdread, &fdwrite, &fdexcep, &maxfd);
if (mc != CURLM_OK) {
throw new Exception("MC error code: " + mc);
break;
}
if (maxfd == -1) {
Sleep(1000);
rc = 0;
} else {
rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
}
switch (rc) {
case -1:
/* select error */
std::cout << "Error" << std::endl;
break;
case 0:
/* timeout */
std::cout << "Timeout" << std::endl;
break;
default:
/* action */
std::cout << "Action" << std::endl;
curl_multi_perform(_curlm, &_isRunning);
break;
}
} while (_isRunning);
while ((_msg = curl_multi_info_read(_curlm, &_msgsLeft))) {
std::cout << "RAN";
if (_msg->msg == CURLMSG_DONE) {
for (unsigned int i = 0; i < _requests.size(); i++) {
Request request = _requests[i];
if (_msg->easy_handle == request.curl) {
std::cout << request.response << std::endl;
break;
}
}
}
}
curl_multi_cleanup(_curlm);
for (unsigned int i = 0; i < _requests.size(); i++) {
curl_easy_cleanup(_requests[i].curl);
_requests.erase(_requests.begin() + i);
}
}
}
RequestHandler.h
#pragma once
#include <string>
#include <vector>
#include "curl\curl.h"
#include "Lua\lua.hpp"
struct Request {
std::string response;
std::string headers;
int code;
CURL* curl;
lua_State* lua;
};
class RequestHandler {
public:
RequestHandler();
~RequestHandler();
static RequestHandler* getInstance();
void add(lua_State* lua, const std::string& url, const std::string& data);
void tick();
private:
static RequestHandler* INSTANCE;
std::vector<Request> _requests;
CURLM* _curlm;
CURLMsg* _msg;
int _isRunning;
int _msgsLeft;
};
Update
As suggested in the comment I used CURLOPT_STDERR and CURLOPT_VERBOSE and nothing printed to the output file.
I added this code within the RequestHandler:add(); function.
#ifdef _DEBUG
FILE* file = fopen("../Logs/Verbose.log", "wb");
curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
curl_easy_setopt(curl, CURLOPT_STDERR, file);
#endif
The file does get created but nothing get written to the file.
Related
I have a program that returns a long string from a curl request, the code is as follows:
#include <iostream>
#include <string>
#include <curl/curl.h>
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
int main(void)
{
std::string s;
CURL* curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, "www.ecobliss.co.za/run_student_query.php?query=Select%20*%20FROM%20data%20WHERE%20ID%20%3C%2030");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
std::cout << s << std::endl;
struct curl_slist* headers = NULL;
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
}
curl_easy_cleanup(curl);
//std::cout << s;
std::string arr[10000];
int i = s.find_first_of("ID");
//std::cout << i<<std::endl;
int ic = 0;
while (i>0) {
std::cout << i;
if (i > 0) {
arr[ic] = s.substr(i, i + 6);
s.erase(i,i+1);
int i = s.find_first_of("ID");
std::cout << i;
}
if (i < 0) {
break;
}
ic++;
}
for (ic = 0; ic < std::size(arr); ic++) {
std::cout << arr[ic];
}
return 0;
}
the output of the request in postman is:
<p>Results from your query:</p>
<br>{"ID":"26","datetime":"2022-03-13 03:21:07","temperature":"25.3","humidity":"80.9","pressure":"1020.2"}<br>{"ID":"27","datetime":"2022-03-13 05:12:47","temperature":"24.8","humidity":"82.1","pressure":"1020.5"}<br>{"ID":"28","datetime":"2022-03-13 05:29:05","temperature":"24.9","humidity":"83.6","pressure":"1020.5"}<br>{"ID":"29","datetime":"2022-03-13 05:29:07","temperature":"24.9","humidity":"83.8","pressure":"1020.5"}
I have tried to use string handling and extract the value the ID part holds, but it does not work at all, can someone please help.
Using refresh to get the output result from as Flask web server, when the function is executed it prints the result needed to the screen but when it is time to print out it does not print the out value and all you get is an empty line
Why is this happening
size_t CurlWrite_CallbackFunc_StdString(void* contents, size_t size, size_t nmemb, std::string* s)
{
size_t newLength = size * nmemb;
try
{
s->append((char*)contents, newLength);
}
catch (std::bad_alloc& e)
{
//handle memory problem
return 0;
}
return newLength;
}
std::string refresh(std::string path) {
CURL* curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
const char* path_ = path.c_str();
std::string s;
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, path_);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "out=");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
/* always cleanup */
curl_easy_cleanup(curl);
}
std::cout << s << std::endl;
return s;
}
driver code
int main() {
std::string out = refresh(server_path+"/refresh");
std::cout << out << std::endl;
}
I am very new to libcurl. So any help is appreciated.
I am trying to download multiple files from CDN. The total size is around 600mb.
This is the piece of code where I am setting CURL handles(Inside a method named "addTransfers()"). (cm is of type CURLM*)
CURL *ceh = curl_easy_init();
curl_easy_setopt(ceh, CURLOPT_URL, reqURL.c_str());
curl_easy_setopt(ceh, CURLOPT_USERPWD, usrpwd);
curl_easy_setopt(ceh, CURLOPT_WRITEDATA, file);
curl_easy_setopt(ceh, CURLOPT_PRIVATE, file);
curl_easy_setopt(ceh, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(ceh, CURLOPT_FAILONERROR, 1L);
curl_easy_setopt(ceh, CURLOPT_CONNECTTIMEOUT, 10L);
curl_easy_setopt(ceh, CURLOPT_TIMEOUT, 150L);
curl_multi_add_handle(cm, ceh);
This is the code where I am performing the curl multi process:
bool do_multiple_downloads()
{
CURLM *cm;
CURLMsg *msg;
unsigned int transfers = 0;
int pending = 1;
int msg_pending = -1;
curl_global_init(CURL_GLOBAL_ALL);
cm = curl_multi_init();
curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, maxConnects);
for(transfers = 0; transfers < (int)maxConnects; transfers++)
{
if(!addTransfers(cm, transfers))
{
//Error
return false;
}
}
int i = 0;
do
{
/* code */
CURLMcode cPerformCode = curl_multi_perform(cm, &pending);
if(cPerformCode != CURLM_OK)
{
fprintf(stderr, "Error --> (%s) : Pending --> (%d)", curl_multi_strerror(cPerformCode), pending);
return false;
}
while((msg = curl_multi_info_read(cm, &msg_pending)))
{
if(msg != NULL)
{
if(msg->msg == CURLMSG_DONE)
{
FILE* writtenFile;
char* fname;
CURL *e = msg->easy_handle;
curl_easy_getinfo(e, CURLINFO_PRIVATE, &writtenFile);
fprintf(stderr, "R: %d - %s (%d)\n",
msg->data.result, curl_easy_strerror(msg->data.result), i++);
curl_multi_remove_handle(cm, e);
fclose(writtenFile);
curl_easy_cleanup(e);
}
else
{
fprintf(stderr, "E: CURLMsg (%d) : (%d)\n", msg->msg, i++);
}
if(transfers < totalSize)
{
if(!addTransfers(cm, transfers++))
{
//Error
fprintf(stderr, "Additional transfers addition\n");
return false;
}
}
}
}
if(pending)
{
curl_multi_wait(cm, NULL, 0, 1000, NULL);
}
} while (pending || (transfers < totalSize));
curl_multi_cleanup(cm);
curl_global_cleanup();
return true;
}
These are the scenarios:
Sometimes it works fine and all files are downloaded - No problem
Sometimes the downloads are completed, but the program is still inside the do-while loop(pending variable never becomes zero)
If I disconnect from the internet when the process is happening, the program stays inside the do-while loop. When I reconnect to the internet, Scenario 2 occurs.
Am I missing something here?? I might have done something silly here. Not sure though.
Thanks in advance.
I have an application which is using LibCurl to upload files. I'm showing the upload progress with the percentage with the underneath function which works great. However, I can't get the average upload speed (CURLINFO_SPEED_UPLOAD) nor the time elapsed (CURLINFO_TOTAL_TIME) with the curl_easy_getinfo function. What am I doing wrong here? I can't see much differences with the original example from Libcurl?
static int ReceiveFileProgress(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) {
if (ultotal > 0) {
string Output;
double curtime = 0;
char ulspeed[10000];
double ulspeed_curl = 0;
double ulnow_db = (double)ulnow;
double ultotal_db = (double)ultotal;
double percentage = ceil((ulnow_db / ultotal_db) * 100);
struct myprogress *myp = (struct myprogress *)p;
CURL *curl = myp->curl;
if (curl) {
cout << "CURL OK" << endl;
}
else {
cout << "CURL FAILED" << endl;
}
if (percentage != 100) {
curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &ulspeed_curl);
}
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &curtime);
readable_fs(ulspeed_curl, ulspeed);
stringstream OutputStream;
OutputStream << percentage;
Output = PadString(OutputStream.str(), 3, " ");
OutputStream.str("");
OutputStream << Output << "%";
if (percentage != 100) {
OutputStream << " (" << ulspeed << "/s)";
}
Output = OutputStream.str();
if (Output.length() > SendOffFileMaxProgressLength) {
Output.substr(0, SendOffFileMaxProgressLength - 3);
Output += "...";
}
else {
while (Output.length() < SendOffFileMaxProgressLength) {
Output += ' ';
}
}
cout << Output << '\r';
}
return 0;
}
The curl request:
string PerformCurlRequest(string RequestType, struct curl_httppost &formpost, struct curl_httppost &lastptr) {
CURL *curl;
CURLcode res;
bool UsedProxy;
string CurlResponse;
int LibCurlError = 0;
int ProxyRetryCount = 1;
bool TryWithProxy = true;
struct curl_slist *LibcurlHeaders = NULL;
curl = curl_easy_init();
if (curl) {
host = "url/";
host += RequestType;
host += "/";
LibcurlHeaders = curl_slist_append(LibcurlHeaders, "Expect:");
curl_easy_setopt(curl, CURLOPT_URL, (host).c_str());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, LibcurlHeaders);
curl_easy_setopt(curl, CURLOPT_VERBOSE, CurlVerbose);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, LibcurlResponse);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &CurlResponse);
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, GetCurlVerboseData);
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, ReceiveFileProgress);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &progress);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false);
res = curl_easy_perform(curl);
curl_slist_free_all(LibcurlHeaders);
curl_easy_cleanup(curl);
}
return CurlResponse;
}
Send off File:
PerformCurlRequest("SendFile", *formpostReceiveFile, *lastptrReceiveFile)
I don't know what libcurl version you're using or if you perhaps mess up your code somewhere else, but I can certainly make CURLINFO_SPEED_UPLOAD from within a libcurl progress callback in this example code doing HTTP "upload" (using a PUT here for simplicity):
#include <stdio.h>
#include <curl/curl.h>
#include <sys/stat.h>
struct myprogress {
CURL *curl;
};
static int xferinfo(void *p, curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow)
{
struct myprogress *myp = (struct myprogress *)p;
CURL *curl = myp->curl;
double ulspeed_curl = 0;
curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &ulspeed_curl);
fprintf(stderr, "UP: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
" DOWN: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
" AVRUP: %.1f"
"\r\n",
ulnow, ultotal, dlnow, dltotal, ulspeed_curl);
return 0;
}
/* send off a random test file lying around */
#define FILENAME "file-to-send"
int main(void)
{
CURL *curl;
CURLcode res = CURLE_OK;
struct myprogress prog;
curl = curl_easy_init();
if(curl) {
FILE *strace;
struct stat file_info;
prog.curl = curl;
strace = fopen(FILENAME, "rb");
if(!strace)
return 1;
/* get the file size of the local file */
stat(FILENAME, &file_info);
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/");
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
(curl_off_t)file_info.st_size);
curl_easy_setopt(curl, CURLOPT_READDATA, strace);
res = curl_easy_perform(curl);
if(res != CURLE_OK)
fprintf(stderr, "%s\n", curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
return (int)res;
}
In the project I am working on , I am required to make a GET call and POST call when ever necessary. The "GET" call is used to create a downchannel from the server to the device to monitor for any interesting events that are happen in the cloud server. The "POST" call is used to send the data to the server. The server has a restriction that only a single connection has to be maintained with the server. Since the server supports HTTP2 , I am using "CURLMOPT_MAX_HOST_CONNECTIONS" and by setting it to 1 , I am making CURL to use 1 connection and I am using CURLMOPT_PIPELINING and by setting it to CURLPIPE_MULTIPLEX , I am multiplexing the transfers. The issue is that the code crashes when "curl_multi_perform" is called on the second thread.
PS: This is a part of my original code and might not compile/run straight away.
#include <stdio.h>
#include <string>
#include <sstream>
#include <curl.h>
#include <pthread.h>
#define EVENTS_URL "https://avs-alexa-na.amazon.com/v20160207/events"
#define DOWNCHANNEL_URL "https://avs-alexa-na.amazon.com/v20160207/directives"
CURLM *multi_handle;
CURL *downchannel_handle;
CURL *eventHttp_handle;
size_t processDownchannelResponse(void *ptr, size_t size, size_t nmemb, void *instance)
{
printf(" There is downchannel response.");
}
size_t eventResponse(void *ptr, size_t size, size_t nmemb, void *instance)
{
printf("We got eventResponse");
}
/* The downchannel thread needs to be running always
, if the transfer is done the connection is closed
we need to open a new connection and wait for more events*/
void createDownchannel()
{
int retryCount =0;
std::string downchURL = DOWNCHANNEL_URL;
long response_code;
int runninghandles =0;
downchannel_handle = curl_easy_init();
if(downchannel_handle == NULL){
printf("createDownchannel : Not able to create curl handle");
return ;
}
struct curl_slist *header = NULL;
header = curl_slist_append(header, "Host: avs-alexa-na.amazon.com");
header = curl_slist_append(header, "TOKEN GOES HERE");
curl_easy_setopt(downchannel_handle, CURLOPT_URL, downchURL.c_str());
curl_easy_setopt(downchannel_handle, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(downchannel_handle, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(downchannel_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
curl_easy_setopt(downchannel_handle, CURLOPT_WRITEFUNCTION, processDownchannelResponse);
curl_easy_setopt(downchannel_handle, CURLOPT_WRITEDATA, NULL);
curl_easy_setopt(downchannel_handle, CURLOPT_PIPEWAIT, 1L);
if (header)
curl_easy_setopt(downchannel_handle, CURLOPT_HTTPHEADER, header);
if(multi_handle)
/* add the individual easy handle */
curl_multi_add_handle(multi_handle, downchannel_handle);
mbexitdownchannelthread = 1;
do{
CURLMcode mc;
int numfds;
mc = curl_multi_perform(multi_handle, &runninghandles);
if(mc != CURLM_OK) {
fprintf(stderr, "curl_multi failed, code %d.n", mc);
printf(“a<---curl_multi failed, code %d.n", mc);
break;
}
printf("a<--downchannel while");
// downchannel timeout can be higher 10 seconds
mc = curl_multi_wait(multi_handle, NULL, 0, 10000, &numfds);
if(mc != CURLM_OK) {
fprintf(stderr, "curl_multi failed, code %d.n", mc);
printf("a<---curl_multi failed, code %d.n", mc);
break;
}
}while(!mbexitdownchannelthread);
curl_multi_remove_handle(multi_handle, downchannel_handle);
curl_easy_cleanup(downchannel_handle);
if (header)
curl_slist_free_all(header);
}
bool getTransferStatus(CURLM *multiHandleInstance,CURL *currentHandle,std::string& contentType,int* http_status_code)
{
//check the status of transfer CURLcode return_code=0;
int msgs_left=0;
CURLMsg *msg=NULL;
CURL *eh=NULL;
CURLcode return_code;
bool msgTrasferDone = false;
while ((msg = curl_multi_info_read(multiHandleInstance, &msgs_left)))
{
if (msg->msg == CURLMSG_DONE) {
eh = msg->easy_handle;
if(currentHandle == eh)
{
msgTrasferDone = true;
return_code = msg->data.result;
if(return_code!=CURLE_OK)
{
//fprintf(stderr, "CURL error code: %d\n", msg->data.result);
printf("a<--return_code!=CURLE_OK CURL error code: %d\n", msg->data.result);
continue;
}
// Get HTTP status code
*http_status_code=0;
char* ch= NULL;
curl_easy_getinfo(eh, CURLINFO_RESPONSE_CODE, http_status_code);
printf("a<--CURLINFO_RESPONSE_CODE=%d",*http_status_code);
curl_easy_getinfo(eh, CURLINFO_CONTENT_TYPE, &ch);
contentType.clear();
if(ch!=NULL)
contentType.append(ch);
}
}
}
return msgTrasferDone;
}
int eventThread()
{
int still_running = 0;
std::string contentType;
int responseCode = 0;
int numfds = 0;
std::string postUrl;
postUrl.assign(EVENTS_URL);
// init the curl session
CURL *eventHttp_handle;
CURLcode res;
eventHttp_handle = curl_easy_init();
//assign speech buffer pointer for read callbacks
curl_easy_setopt(eventHttp_handle, CURLOPT_URL, postUrl.c_str());
curl_easy_setopt(eventHttp_handle, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(eventHttp_handle, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(eventHttp_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
/* wait for pipe connection to confirm */
curl_easy_setopt(eventHttp_handle, CURLOPT_PIPEWAIT, 1L);
curl_easy_setopt(eventHttp_handle, CURLOPT_WRITEFUNCTION, eventResponse);
curl_easy_setopt(eventHttp_handle, CURLOPT_WRITEDATA, NULL);
struct curl_slist *header = NULL;
header = curl_slist_append(header, "Host: avs-alexa-na.amazon.com");
header = curl_slist_append(header, "TOKEN GOES HERE");
if (header)
curl_easy_setopt(eventHttp_handle, CURLOPT_HTTPHEADER, header);
if (multi_handle)
curl_multi_add_handle(multi_handle, eventHttp_handle);
do
{
{
CURLMcode mc;
int numfds;
mc = curl_multi_perform(multi_handle, &still_running);
if(mc != CURLM_OK) {
fprintf(stderr, "curl_multi failed, code %d.n", mc);
printf("a<---curl_multi failed, code %d.n", mc);
break;
}
mc = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);
if(mc != CURLM_OK) {
fprintf(stderr, "curl_multi failed, code %d.n", mc);
printf("a<---curl_multi failed, code %d.n", mc);
break;
}
}
}while(!getTransferStatus(multi_handle,eventHttp_handle,contentType,&responseCode));
if (header)
curl_slist_free_all(header);
if (formpost)
{
curl_formfree(formpost);
formpost = NULL;
}
printf("a<-- CURL HTTP RESP CODE =%d",responseCode);
curl_multi_remove_handle(multi_handle, eventHttp_handle);
curl_easy_cleanup(eventHttp_handle);
return 0;
}
int main ()
{
multi_handle = curl_multi_init();
curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
curl_multi_setopt(multi_handle, CURLMOPT_MAX_HOST_CONNECTIONS, 1L);
// create a downchannel thread
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int err = pthread_create(&mPostThread, &attr, downchannelThread,NULL);
pthread_attr_destroy(&attr);
// i am doing some work here //
sleep(3);
// create a event thread
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int err = pthread_create(&mPostThread, &attr, eventThread,NULL);
pthread_attr_destroy(&attr);
}