0

多くのファイルのフォルダをダウンロードしながら、現在のダウンロード速度を計算する方法を見つけようとしています(ダウンロードしているのは単一のファイルではありません)。そして、私はそれを正しく行うことができず、今では何時間もそれを経験しているので、混乱しすぎています。ダウンロード速度が速すぎる場合や、0になる場合があります。

私はcurlとc++を使用しています。

私のダウンロード機能では、プログラムはすべてのファイルがダウンロードされるまで各ファイルを再帰的にダウンロードします。

これは、ダウンロード中にTraceProgress関数を呼び出すようにcurlを設定する方法です。

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

どんな助けでも大歓迎です。どうもありがとう。

4

1 に答える 1

1

dlnow - oldDownloadNowおそらく間違っています。dlnow代わりに使用する必要があります。ダウンロード速度の変化率oldDownloadNowを表示したい場合を除いて、まったく必要ありません。

`dltotal`と`dlnow`の名前に戸惑いました。`dltotal`はダウンロードされた*予想される*合計バイト数であり、`dlnow`はこれまでにダウンロードされたバイト数です。したがって、 `oldDownloadNow`が必要であり、`dlnow--oldDownloadNow`が現在のデルタです。

このフラグメント

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

エラーがあります:oldDownloadNow == dlnow前回から何もダウンロードされていないことを意味します。この場合、現在の瞬間的なダウンロード速度はゼロです。フラグメントは次のように置き換える必要があります

    downloadSinceLastIteration = dlnow - oldDownloadNow;

何もチェックせずに。libcurl突然それを決定した場合oldDownloadNow > dlnow、これは適切に負のダウンロード速度を表示します。これは正しいことです。意図的にエラーを非表示にしないでください。

また、time()解像度が粗すぎます。ある種のきめの細かいタイマーを使用します。

于 2012-12-09T16:08:18.777 に答える