c++ - 下载速度到处跳

标签 c++ winapi libcurl

我有一个小程序可以使用 curl 从 ftp 下载文件。在 CURLOPT_PROGRESSFUNCTION 中传递的函数中,我计算了下载速度,问题是下载速度到处跳跃,在 2mbps 的互联网连接上从 512kbps 到 8mbps。我无法确定这里出了什么问题。

编辑: 我更改了代码以计算读数的平均值,curl 下载的问题是您无法预测何时调用 TraceProgress 函数,它可以在不到 1 的时间内再次调用第二,所以程序等待 5 次迭代记下读数,并在取平均值之前取 6 个这样的读数,我还考虑了自上次读取以来耗时(秒),因为我们不能保证 TraceProgress 函数将被同时调用间隔。

如果现在看起来好多了,请告诉我。

代码如下:

int minorCounter = 0;
int majorCounter = 0;

int minorCycle = 4;
int majorCycle = 5;

double blockDL[6];
double blockTime[6];

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

  if ( minorCounter == minorCycle )
    {

            blockDL[majorCounter] = dlnow - oldDownloadNow;

            myTimer.Tick();
            blockTime[majorCounter] = myTimer.GetDurationInSecs();

            minorCounter = 0;


            if ( majorCounter == majorCycle )
            {
                double dl = 0;
                double tm = 0;

                for ( int i = 0; i < majorCycle ; i++ )
                {
                    dl += blockDL[i];
                    tm += blockTime[i];
                }

                dl = dl/(majorCycle+1);

                tm = tm/(majorCycle+1);

                double currentDownloadSpeed = dl / tm;

                /* download speed - divide by 1024 to get speed in kilobytes instead of bytes */
                double idownloadSpeed = currentDownloadSpeed / 1024;

                string post;
                if ( idownloadSpeed > 1024 )
                {
                       idownloadSpeed = idownloadSpeed / 1024;
                       post = " MB/s";
                }
                else
                {
                        post = " KB/s";
                }

                string downloadSpeed = DoubleToString( idownloadSpeed );

                size_t x = downloadSpeed.find( "." );
                downloadSpeed.erase( x+2 );

                downSize = "Download Speed:  " + downloadSpeed + post;
                SendMessage( hDownloadSpeedSTATIC, WM_SETTEXT, (WPARAM)0, (LPARAM)downSize.c_str() );

                majorCounter = 0;
            }
            else
            {
                majorCounter++;
            }

            oldDownloadNow = dlnow;
            myTimer.Start();
    }
    else
    {
            minorCounter++;
    }

    return 0;
}

最佳答案

您需要使用采样窗口和指数衰减或其他合理的方法。

如果每 30 分钟就有一辆汽车从装配线上下线,而您只取了一个样本,就会发生可怕的事情。例如,如果您在汽车下线后立即采样,然后在 20 分钟后再次采样,您将在 20 分钟内看到零辆汽车,即每小时零辆汽车。如果您在一辆汽车下线之前采样,并在 31 分钟后再次采样,您将在 31 分钟内看到两辆汽车,即每小时 3.9 辆汽​​车。

这是一个简单的算法:

  1. 保持单次计数和单次平均速度。从零开始。

  2. 每秒更新一次。

  3. 每一秒,首先将前一秒接收到的字节数加到计数中。

  4. 添加计数后,从计数中减去计数的 1/8。 count -= (count/8);

  5. 将平滑后的平均速度(以每秒 为单位)更新为当前计数。 bits_per_sec = count;

要了解此算法为何有效,请假设计数是常量。这意味着添加到计数中的数量必须等于减去的数量。这意味着计数必须是每秒添加的字节数的 8 倍,即每秒接收的位数。

关于c++ - 下载速度到处跳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13984931/

相关文章:

c++ - 使用 gzip 压缩 POCO HttpResponse 来削减内容

c++ - 如何拦截消息: "WM_QUIT || WM_DESTROY || WM_CLOSE" WinAPI

c++ - 使用 Qt Creator 构建时找不到库

python - 使用 pycurl 发布文件并传递参数

linux - Libcurl 未更新

c++ - Qt连接: Using Lambda Expression Resets Passed int Variable (Weird)

c++ - 创建自定义锁屏 Windows 7

multithreading - 当我在Winsock connect函数中强制终止线程时会发生什么?

c++ - 为 OpenGL 设置剪切矩形?

php - 将 php curl 转换为用于 iTunes InApp verifyReceipt 的 GAE urlfetch