Libcurl和HTTP管道

时间:2015-08-25 22:39:17

标签: http libcurl

Libcurl提供CURLOPT_HEADERFUNCTION和CURLOPT_WRITEFUNCTION回调。在你使用流水线和多线程之前,这很棒。你如何将标题与身体联系起来?假设大量请求和大量简单句柄导致libcurl与服务器建立多个连接。假设第一个响应头到达,并且接收正文有延迟。同时,第二个标题与身体一起显示。 libcurl是否确保在第一个响应完成之前第二个标头未传递给应用程序? 这很重要,因为标题需要与正文相关联。即使我不使用HEADERFUNCTION,我也处于同样的困境。即使我只使用WRITEFUNCTION,它也可能以混合方式无序接收回复。所以问题是:libcurl是否确保响应是作为一个整体传递的?如果是单个连接,我们可以确定响应顺序将遵循请求顺序。但是我看到libcurl在使用pipeling和multistack时建立了多个连接。假设有5个连接到同一个服务器,因为我们在这里讨论的是Pipelining。 Conn1的响应标头到达,在我们从Conn1获取主体之前,我们从Conn2获得ResponseHeader。 LibCurl是否确保在BodyFromConn1之前未将Conn2ResponseHeader传递给应用程序?否则,下面的代码将会中断。

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;
}

};

1 个答案:

答案 0 :(得分:0)

为什么不将案例CEasyHandle用作WRITEFUNCTION的用户数据?在创建它们时,在每个CMultiStack中存储一个指向CEasyHandle的指针?然后,您始终可以在write_callback中找到所需的任何部分,而无需担心订单。