我有一個跨平臺嵌入式libCurl客戶端應用程序運行在一個powerpc上,其行爲與其窗口相對應。基本問題是我的客戶端上傳文件的遠程服務器在返回226響應(表示成功上傳)之前執行了非常長的操作。此時遠程FTP服務器實際上正在執行閃回回收,此操作最多可能需要900秒。實際上,我試圖在等待遠程226或錯誤響應時使用數據非活動超時。libCurl上傳數據不活動超時不工作
在windows上,這個工作正常,但是在PowerPC嵌入式客戶端(我們鏈接最新的libCurl-7.39.0庫,使用Mentor Graphics Code Sourcery工具鏈編譯爲PowerGNU),客戶端在FTP非活動時間超過60秒後超時。
予設定的定時器如示於下剪斷的代碼(注意,我確保CURLOPT_FTP_RESPONSE_TIMEOUT具有比CURLOPT_TIMEOUT 1秒較低的值。此外,值得注意的是,CURLOPT_CONNECTTIMEOUT被設定爲所述的方式60秒(也許這是巧合,但是需要CURLOPT_CONNECTTIMEOUT(即60秒),以便在powerPC linux客戶端上將非活動狀態設爲超時)。我想知道CURLOPT_CONNECTTIMEOUT中是否存在某個錯誤,它會覆蓋或破壞Linux客戶端上的CURLOPT_FTP_RESPONSE_TIMEOUT ?
除此之外,我的捲曲選項似乎工作正常。我讀了一個article關於libCurl中定時器的實現,其中看起來定時器是組織在某種'先到期'的順序,也許在我更新默認CURLOPT_FTP_RESPONSE_TIMEOUT(默認爲不確定)時,它的插入會導致定時器隊列的損壞。
// if updating the module could potentially
// cause flash reclamation, set the command to response FTP
// timer to include both delivery time + the max expected
// time for the file put for the biggest file over BASE2 or BASET
auto flashReclTimeout = rContext.getFlashReclTimeout();
if (flashReclTimeout) {
auto timeoutSecs = duration_cast<seconds>(flashReclTimeout.get());
auto res = curl_easy_setopt(rContext.getCurlHandle(),
CURLOPT_TIMEOUT, timeoutSecs.count()+1);
res = curl_easy_setopt(rContext.getCurlHandle(),
CURLOPT_FTP_RESPONSE_TIMEOUT, timeoutSecs.count());
ss << ", [flash reclamation timeout "
<< timeoutSecs.count()
<< "(s)]";
}
LOG_EVT_INFO(gEvtLog) << rLogPrefix << ss.str() << std::endl;
我的默認libcurl的選項設置如下
/**
* Sets the curl options using the current mContextInfo.
*
* This never sets the URI curl field as this must be
* done outside the context object.
*/
void
SLDBContext::setCurlOptions() {
CURL* pCurl = mCurlHandle.get();
// reset all curl context info
curl_easy_reset(pCurl);
// DEOS does not support EPSV or EPRT
auto res = curl_easy_setopt(pCurl, CURLOPT_FTP_USE_EPSV, 0L);
res = curl_easy_setopt(pCurl, CURLOPT_FTP_USE_EPRT, 0L);
res = curl_easy_setopt(pCurl, CURLOPT_NOSIGNAL, 1L);
#if 0
// send out TCP keep-alive probes - not required
res = curl_easy_setopt(pCurl, CURLOPT_TCP_KEEPALIVE, 1L);
// check to ensure that this is supported
if (res == CURLE_OK) {
// wait for at least 30 seconds before sending keep-alive probes
// every 2 seconds
res = curl_easy_setopt(pCurl, CURLOPT_TCP_KEEPIDLE, 30L);
res = curl_easy_setopt(pCurl, CURLOPT_TCP_KEEPINTVL, 30L);
}
#endif
// do not perform CWD when traversing the pseudo directories
res = curl_easy_setopt(pCurl, CURLOPT_FTP_FILEMETHOD, CURLFTPMETHOD_NOCWD);
res = curl_easy_setopt(pCurl, CURLOPT_CONNECTTIMEOUT, getConnectTimeoutSecs());
if (!isPASVMode()) {
res = curl_easy_setopt(pCurl, CURLOPT_FTPPORT, "-");
}
// used to capture header traffic
if (mHeaderCallback) {
res = curl_easy_setopt(pCurl, CURLOPT_WRITEHEADER, mpHeaderStream);
res = curl_easy_setopt(pCurl, CURLOPT_HEADERFUNCTION, mHeaderCallback);
}
// for FTP GET operations
if (mWriteDataCallback) {
res = curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, &mScratchBuffer);
res = curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, mWriteDataCallback);
}
// for FTP PUT operations
if (mReadFileCallback) {
res = curl_easy_setopt(pCurl, CURLOPT_READFUNCTION, mReadFileCallback);
}
// @JC this feature may be causing slowdowns on the target platform
#if 0
// capture error details to this buffer
res = curl_easy_setopt(pCurl, CURLOPT_ERRORBUFFER, mErrorBuffer.get());
#endif
// progress callback used to track upload progress only
if (mProgressCallback) {
res = curl_easy_setopt(pCurl, CURLOPT_XFERINFOFUNCTION, mProgressCallback);
res = curl_easy_setopt(pCurl, CURLOPT_NOPROGRESS, 0L);
res = curl_easy_setopt(pCurl, CURLOPT_XFERINFODATA, nullptr);
}
// verbose logging
if (mDebuggingCallback) {
res = curl_easy_setopt(pCurl, CURLOPT_VERBOSE, 1L);
res = curl_easy_setopt(pCurl, CURLOPT_DEBUGFUNCTION, mDebuggingCallback);
res = curl_easy_setopt(pCurl, CURLOPT_DEBUGDATA, nullptr);
} else {
res = curl_easy_setopt(pCurl, CURLOPT_VERBOSE, 0L);
res = curl_easy_setopt(pCurl, CURLOPT_DEBUGDATA, nullptr);
}
// disable Nagle algorithm - to fix slowdown in bulk transfers
// with large data files @JC not necessary
// res = curl_easy_setopt(pCurl, CURLOPT_TCP_NODELAY, 1L);
if (mSocketOptionCallback) {
res = curl_easy_setopt(pCurl, CURLOPT_SOCKOPTDATA, nullptr);
res = curl_easy_setopt(pCurl, CURLOPT_SOCKOPTFUNCTION, mSocketOptionCallback);
}
}
也許你還需要http://curl.haxx.se/libcurl/c/CURLOPT_ACCEPTTIMEOUT_MS.html如果你的數據傳輸使用被動ftp? – 2014-12-15 08:03:28
如果您想要「空閒超時」,您應該設置「PROGRESSFUNCTION」並實施您自己的邏輯來確定連接是否卡住。 – 2014-12-15 08:04:58