年末出大坑,目前博主项目中对外提供的设备接口库涉及到网络通信,部分HTTP请求概率性出现【CURLE_RECV_ERROR】问题。博主使用的是libcurl第三方库进行http请求,由于网上没有查到相关资料,下面记录一下,本次问题分析和解决办法,希望能给其他人提供解决思路。
通过Wireshark抓包,我对比了正常时候的HTTP流和异常时候的HTTP流。
异常HTTP流
正常HTTP流
当出现【CURLE_RECV_ERROR】问题时,客户端向服务器发送POST请求,服务器未响应,6次TCP重传无响应后,【libcurl】判定HTTP数据接收失败。
我将数据包发聩给服务端研发人员,最后平台扩大了连接池设置予以解决。
通过问题定位,已经能确定是服务器的问题,在问题还未解决的情况下,我这边找到一个容错方法,即CURL句柄先调用其它正常的接口后,再调用出问题的接口,能收到正常返回。
我这边贴上容错代码:
QCARD_CURL *pHandle = (QCARD_CURL *)hCurlHandle;
char pcUrlGetIssue[128] = {0}, pcParameter[1024] = {0};
CURL *curl_handle = 0;
CURLcode res = CURLE_OK;
int ret = 0;
sprintf(pcUrlGetIssue, "http://%s/fillqkey/distrQKeyByBlock", pHandle->pcSystenAddr);
curl_handle = curl_easy_init();
curl_easy_setopt(curl_handle, CURLOPT_URL, pcUrlGetIssue);//set down load url
curl_easy_setopt(curl_handle, CURLOPT_POST, 1);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, pHandle);//set download file
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, read_head_fun);//set call back fun
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);//设定为不验证证书和host
if(pHandle->uiTimeOut)
{
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, pHandle->uiTimeOut);
}
sprintf(pcParameter, "deviceId=%s&unitId=%s&perBlockSeq=%d&devAuthCode=%s", pcStoreId, pcUnitId, *puiperBlockSeq, pcMacCode);
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, pcParameter);
memset(pHandle->pcError, 0, sizeof(pHandle->pcError));
/* 容错:CURLE_RECV_ERROR */
if(1)
{
curl_easy_setopt(curl_handle, CURLOPT_URL, "http://112.27.xx.xxx:xxxxx/fillqkey/createFillQKeyTask");//set down load url
res = curl_easy_perform(curl_handle);
curl_easy_setopt(curl_handle, CURLOPT_URL, pcUrlGetIssue);//set down load url
QCARD_FREE(pHandle->msg);
}
res = curl_easy_perform(curl_handle);
if(res != CURLE_OK)
{