2012-12-09 74 views
0

我想弄清楚如何計算當前下載速度,同時下載許多文件的文件夾(它不是一個單一的文件,我正在下載)。而且我無法正確地做到這一點,現在經歷了好幾個小時,它變得太混亂了。下載速度有時會變得太高,有時它的0.在curl和C++中測量下載速度。我做得對嗎?

我正在使用curl和c + +。

在我的下載功能中,程序遞歸地下載每個文件,直到所有的文件都被下載。

這是我設置捲曲如何下載過程中調用TraceProgress功能:

curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, TraceProgress); 
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &response); 
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); 

這裏是剩餘代碼:

double totalDownloadableSize = 0; // total size of the download, set prior to starting download of the first file 
    double downloadedSizeTillNow = 0; // total size downloaded till now - keep adding file size that just completed downloading 
    double currentDownloadingSize = 0; // size that we are downloading - downloadedSizeTillNow + bytes downloaded of the current file (in TraceProgress Function) 
    double oldDownloadNow = 0; // size of the old download bytes of that particular file 


    string fileDownloading = ""; 
    string tempFileDownloading = ""; 

    time_t startSeconds; 
    time_t oldSeconds; 

    int downloadIterationCounter = 0; 




    int TraceProgress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) 
    { 

     // add size downloaded till now of this file to the total size downloaded till now 
     currentDownloadingSize = downloadedSizeTillNow + dlnow; 

     double rem = ((totalDownloadableSize - currentDownloadingSize)/1024)/1024; 

     // get current time in seconds 
     time_t currentSeconds = time (NULL); 

     // get elapsed time since last itiration 
     time_t secondsElapsedSinceLastItiration = currentSeconds - oldSeconds; 

     double downloadSinceLastIteration; 
     if (oldDownloadNow < dlnow)// so that we don't get wrong data when download file changes 
     { 
      downloadSinceLastIteration = dlnow - oldDownloadNow; 
     } 
     else 
     { 
      downloadSinceLastIteration = dlnow; 
     } 

     // calculate current download speed : (dlnow - oldNow)/(current time - oldTime) 
     double currentDownloadSpeed = downloadSinceLastIteration/(double)secondsElapsedSinceLastItiration; 


     // if downloading file name is not same as it was in the last call to this function 
     // change the display text and save the name in the temp. This approach will avoid unnecessory 
     // text change calls. 
     if (fileDownloading.compare(tempFileDownloading) != 0) 
     { 
      tempFileDownloading = fileDownloading; 
      string dlfilename = "Downloading: " + fileDownloading; 
      SetWindowText(hDownloadingSTATIC, dlfilename.c_str());// set text to static control 
     } 


     if (downloadIterationCounter == 4) 
     { 
      std::ostringstream strs_dn; 
      strs_dn << (unsigned int)(rem); 
      std::string downloadNow = strs_dn.str(); 


      string remSize = "Remaining: " + downloadNow + " MB"; 
      SetWindowText(hRemainingDownloadSTATIC, remSize.c_str());// set text to static control 


      double idownloadSpeed = currentDownloadSpeed/1024; 

      std::ostringstream strs_dnSp; 
      strs_dnSp << (unsigned int)(idownloadSpeed); 
      std::string downloadSpeed = strs_dnSp.str(); 

      string downSize = "Download Speed: " + downloadSpeed + " KB/s"; 
      SetWindowText(hDownloadSpeedSTATIC, downSize.c_str());// set text to static control 


      oldSeconds = currentSeconds;// save in old 
      oldDownloadNow = dlnow;// save in old 


      downloadIterationCounter = 0; 
     } 
     else 
     { 
      downloadIterationCounter++; 
     } 

     return 0; 
    } 

任何幫助表示讚賞。非常感謝。

+2

好像你正在編寫一個GUI程序 - 我認爲從主線程以外的任何位置更新UI並不是最好的主意。 – 2012-12-09 16:02:59

+0

也許這就是我遇到奇怪的圖形錯誤的原因,比如應用程序的皮膚變成空白的灰色? :o您建議的正確方法是什麼?下載需要在其獨立的線程中。 – StudentX

+0

爲什麼不問'pthread_main()'這樣做(只更新UI)? – 2012-12-09 16:25:01

回答

1

dlnow - oldDownloadNow可能是錯的。您應該只使用dlnow。除非要顯示下載速度變化率,否則根本不需要oldDownloadNow

I was confused by the `dltotal` and `dlnow` names. `dltotal` is the *expected* total bytes downloaded, and `dlnow` is bytes downloaded so far. So one does need `oldDownloadNow`, and `dlnow - oldDownloadNow` is the current delta.

此片段

if (oldDownloadNow < dlnow) 
    { 
     downloadSinceLastIteration = dlnow - oldDownloadNow; 
    } 
    else 
    { 
     downloadSinceLastIteration = dlnow; 
    } 

有一個錯誤:oldDownloadNow == dlnow表示自上次沒有被下載。在這種情況下,當前的下載速度爲零。該片段應替換爲

downloadSinceLastIteration = dlnow - oldDownloadNow; 

沒有任何檢查。如果libcurl突然決定oldDownloadNow > dlnow,這將正確顯示負面下載速度,這是正確的做法。從不故意隱藏錯誤。

另外,time()分辨率太粗糙。使用某種細粒度的計時器。

+0

查看更新的答案。 –

+0

這是一個很好的觀點,如果oldDownloadNow == dlnow then downloadSinceLastIteration = dlnow - oldDownloadNow;將意味着downloadSinceLastIteration = 0;隨後下載速度將達到0.可能是應該有一個檢查,看看oldDownloadNow == dlnow,在這種情況下什麼都不做?並且,爲了解決文件更改問題,我在下一個文件下載開始前將oldDownloadNow設置爲0,因爲有時候剛剛下載的最後一個文件和oldDownloadNow設置爲更高的值,而新文件的dlnow要低得多,聽起來不錯 ? – StudentX

+2

什麼都不做?爲什麼?當前下載速度爲0,像其他任何速度一樣報告。在文件更改的情況下,您的解決方案聽起來很正確,但您可能需要測試它。 –