【发布时间】:2015-08-25 22:39:16
【问题描述】:
Libcurl 提供 CURLOPT_HEADERFUNCTION 和 CURLOPT_WRITEFUNCTION 回调。在您使用流水线和多堆栈之前,这很好。您如何将标题与正文相关联?假设大量的请求和一堆简单的句柄导致 libcurl 建立到服务器的多个连接。让我们假设第一个响应标头到达,并且接收主体有延迟。同时,第二个标题与正文一起出现。 libcurl 是否确保在第一个响应完成之前不会将第二个标头传递给应用程序? 这很重要,因为标题需要与正文相关联。即使我不使用 HEADERFUNCTION,我也处于同样的困境中。即使我只使用 WRITEFUNCTION,它也可能以混合方式接收乱序的回复。所以问题是:libcurl 是否确保响应作为一个整体交付?如果是单个连接,我们可以确定响应顺序会遵循请求顺序。但是当我使用管道和多堆栈时,我看到 libcurl 建立了多个连接。假设有 5 个连接到同一个服务器,因为我们在这里讨论的是流水线。 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;
}
};
【问题讨论】: