在我正在进行的项目中,我需要在必要时拨打GET电话和POST电话。 “GET”调用用于创建从服务器到设备的下行通道,以监控云服务器中发生的任何有趣事件。 “POST”调用用于将数据发送到服务器。服务器有一个限制,即只需要与服务器维护单个连接。由于服务器支持HTTP2,我使用“CURLMOPT_MAX_HOST_CONNECTIONS”并将其设置为1,我使CURL使用1连接,我使用CURLMOPT_PIPELINING并将其设置为CURLPIPE_MULTIPLEX,我正在复用传输。问题是在第二个线程上调用“curl_multi_perform”时代码崩溃。
PS:这是我原始代码的一部分,可能无法直接编译/运行。
#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);
}