2015-08-25 2 views
0

Libcurl предлагает вызовы CURLOPT_HEADERFUNCTION и CURLOPT_WRITEFUNCTION. Это здорово, пока вы не используете конвейерную обработку и мультистак. Как вы соотносите заголовок с телом? Допустим, тон запросов и множество простых ручек заставляют libcurl устанавливать несколько подключений к серверу. Предположим, что получен первый заголовок ответа, и есть задержка в получении тела. Между тем второй заголовок появляется вместе с телом. Does libcurl гарантирует, что второй заголовок не будет доставлен в приложение до завершения первого ответа? Это важно, потому что заголовок должен быть связан с телом. Я в том же затруднительном положении, даже когда я не использую HEADERFUNCTION. Даже если я использую только WRITEFUNCTION, он может получать ответы не по порядку в смешанном режиме. Поэтому возникает вопрос: ли libcurl гарантирует, что ответы будут переданы в целом? Если это одно соединение, мы можем быть уверены, что заказ ответа будет следовать порядку запроса. Но Я вижу libcurl, делающий несколько соединений, когда я использую pipeling и multistack. Предположим, что 5 соединений сделаны на том же сервере, потому что мы говорим о конвейеризации здесь. Заголовок ответа для Conn1 прибывает. Прежде чем мы получим тело из Conn1, мы получим ResponseHeader из Conn2. Does LibCurl гарантирует, что Conn2ResponseHeader не будет доставлен в приложение до BodyFromConn1? В противном случае следующий код сломается.Libcurl и HTTP Pipelining

class CEasyHandle 
{ 
CURL* m_pCurl; 
bool m_bInUse; 
}; 

class CMultiStack 
{ 
public: 
CURLM* m_pCurlMulti; 
deque<CEasyHandle*>& m_listEasyHandles; 
static CEasyHandle* gpCurrentlyReceivingEasyHandle; 

CEasyHandle* GetAvailableEasyHandle() 
{ 
    // Iterate through m_listEasyHandles and find one that is currently not added to multistack (m_bInUse) 
    // if none free, return NULL 
} 

bool MakeRequest(const char* pUrl) 
{ 
    CEasyHandle* pEasyHandle = GetAvailableEasyHandle(); 
    if(!pEasyHandle) pEasyHandle = CreateNewEasyHandleAndAddToList(); 
    curl_easy_setopt(pEasyHandle->m_pCurl, CURLOPT_HEADERFUNCTION, header_callback); 
    curl_easy_setopt(pEasyHandle->m_pCurl, CURLOPT_HEADERDATA, pEasyHandle); // header gets the EasyHandle 
    curl_easy_setopt(pEasyHandle->m_pCurl, CURLOPT_WRITEFUNCTION, write_callback); 
    curl_easy_setopt(pEasyHandle->m_pCurl, CURLOPT_WRITEDATA, this); // body gets MultiStack 
    // set options, add to multistack, pEasyHandle->m_bInUse = true; 
} 

static size_t header_callback(char *buffer, size_t size, size_t nmemb, void *userdata) 
{ 
    gpCurrentlyReceivingEasyHandle = (CEasyHandle*)userdata; 
    // if no data expected, of course set gpCurrentlyReceivingEasyHandle->m_bInUse = false; 
} 

static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata) 
{ 
    CMultiStack* pThisObj = (CMultiStack*)userdata; 
    pThisObj->PerformSomeWork(); 
    // once complete, gpCurrentlyReceivingEasyHandle->m_bInUse = false; 
} 

};

ответ

0

Почему бы не использовать случай CEasyHandle в качестве данных пользователя для WRITEFUNCTION? И сохраните обратный указатель на CMultiStack в каждом CEasyHandle, когда вы их создадите? Тогда вы всегда можете найти любую деталь, которая вам нужна в write_callback, и вам не нужно беспокоиться о заказе.

Смежные вопросы