计算上传传输速度问题

4
我已经实现了一个文件传输速率计算器,用于显示应用程序中上传过程的kB/sec,然而使用以下代码后,似乎在文件开始上传后我的KB/s读数会出现“突发”。

这是我流代码的一部分,它将一个文件以1024个块的方式流式传输到服务器,使用httpWebRequest:

using (Stream httpWebRequestStream = httpWebRequest.GetRequestStream())
{
    if (request.DataStream != null)
    {
        byte[] buffer = new byte[1024];
        int bytesRead = 0;

        Debug.WriteLine("File Start");
        var duration = new Stopwatch();
        duration.Start();
        while (true)
        {
            bytesRead = request.DataStream.Read(buffer, 0, buffer.Length);
            if (bytesRead == 0)
                break;

            httpWebRequestStream.Write(buffer, 0, bytesRead);
            totalBytes += bytesRead;


            double bytesPerSecond = 0;
            if (duration.Elapsed.TotalSeconds > 0)
                bytesPerSecond = (totalBytes / duration.Elapsed.TotalSeconds);

            Debug.WriteLine(((long)bytesPerSecond).FormatAsFileSize());
        }
        duration.Stop();
        Debug.WriteLine("File End");
        request.DataStream.Close();
    }
}

现在上传过程的输出日志和相应的kB/sec读数如下: (您会注意到一个新文件以 'File Start' 开始,以 'File End' 结束)
File Start
5.19 MB
7.89 MB
9.35 MB
11.12 MB
12.2 MB
13.13 MB
13.84 MB
14.42 MB
41.97 kB
37.44 kB
41.17 kB
37.68 kB
40.81 kB
40.21 kB
33.8 kB
34.68 kB
33.34 kB
35.3 kB
33.92 kB
35.7 kB
34.36 kB
35.99 kB
34.7 kB
34.85 kB
File End

File Start
11.32 MB
14.7 MB
15.98 MB
17.82 MB
18.02 MB
18.88 MB
18.93 MB
19.44 MB
40.76 kB
36.53 kB
40.17 kB
36.99 kB
40.07 kB
37.27 kB
39.92 kB
37.44 kB
39.77 kB
36.49 kB
34.81 kB
36.63 kB
35.15 kB
36.82 kB
35.51 kB
37.04 kB
35.71 kB
37.13 kB
34.66 kB
33.6 kB
34.8 kB
33.96 kB
35.09 kB
34.1 kB
35.17 kB
34.34 kB
35.35 kB
34.28 kB
File End

我的问题是,你会注意到,我所说的“突发”现象始于每个新文件的开头,达到了几兆字节的峰值,然后逐渐平稳。上传会像这样突然增加吗?我的上传速度通常不会超过40k / sec,所以肯定不对。
这是一个真正的问题,当我在屏幕上显示最近5-10秒的平均值时,它会产生一个约为3MB / sec的结果!
有什么好的方法来解决这个问题吗?我应该怎么做?:S
Graham
此外:为什么我不能执行“bytesPerSecond =(bytesRead / duration.Elapsed.TotalSeconds)”,并将duration.Start和duration.Stop移动到while循环中以获得准确的结果?我认为这会更准确?每个速度读取为900字节/秒,800字节/秒等。
3个回答

3
我这样做的方式是:将所有传输的字节保存在一个长整型中。

然后每秒检查一次传输了多少。所以基本上只有每秒触发一次代码来保存速度。在快速网络上,你的while循环会在一秒内循环很多次。

根据您的网络速度,您可能需要在独立的线程或函数中检查传输的字节数。我倾向于使用定时器来实现这一点,这样我就可以轻松地更新UI。

编辑:从你查看你的代码来看,我猜测你做错的事情是你没有考虑到while(true) 中的一个循环不是1秒钟。

编辑2:每秒仅进行一次速度检查的另一个优点是,事情会快得多。在这种情况下,更新UI可能是您正在执行的最慢的事情,因此如果您尝试在每个循环中更新UI,那么这很可能是您的最慢点,并且会产生无响应的UI。

您还正确地指出,您应该平均值化这些值,以便避免出现microsoft minutes错误。我通常通过定时器函数运行来完成此操作,例如:

//Global variables
long gTotalDownloadedBytes;
long gCurrentDownloaded; // Where you add up from the download/upload untill the speedcheck is done.
int gTotalDownloadSpeedChecks;


//Inside function that does speedcheck    
gTotalDownloadedBytes += gCurrentDownloaded;
gTotalDownloadSpeedChecks++;

long AvgDwnSpeed = gTotalDownloadedBytes / gTotalDownloadSpeedChecks; // Assumes 1 speedcheck pr second.

谢谢您的评论,循环确实每1024个块会快速进行一次,但这也是为了平滑地更新进度条,这一切都有效且没有问题。我认为通过将平均等待一秒钟来解决突发情况,不过仍然不确定为什么会出现这种情况。 - GONeale
谢谢EKS,你帮了我很多,我会看看能否进行优化。 - GONeale

2

在您发送数据到系统时,有许多软件和硬件层面的中间环节,其中几个层面有一定数量的缓冲区可用。

当您开始发送数据时,可以快速地输出数据直到填满这些缓冲区 - 但实际上它并没有那么快地到达另一端!在填满发送缓冲区之后,您只能以与其排出数据的速率相同的速度将更多数据放入其中,因此您看到的速率将下降到底层网络发送速率。


0
大家好,我认为通过将5-10个平均变量调整为等待一秒钟来解决问题,已经修复了我的问题。虽然不是最好的方法,但可以让互联网自行处理并允许我捕获平稳的传输。
从我的网络流量中看,似乎出现了爆发,因此在代码中我无法做出任何不同的处理来阻止这种情况。
在我勉强接受自己之前,请仍然希望得到更多答案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接