计算上传传输速度问题

时间:2009-11-09 11:23:34

标签: c# .net networking stream

我已经实现了一个文件传输速率计算器,以显示在我的应用程序中发生的上传过程的kB / sec,但是使用以下代码,似乎我在文件开始时的KB / s读数中得到“爆发”上传。

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

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

我的问题就像你会注意到的那样,我正在谈论的'爆发'从每个新文件的开头开始,在MB中达到峰值,然后正确地均衡。像这样上传到爆发这是正常的吗?我的上传速度通常不会高于40k /秒,所以它不可能是正确的。

这是一个真正的问题,当我平均显示屏幕显示的最后5-10秒时,它确实会产生约3MB /秒的结果!

如果我最接近这个问题的任何想法?我该怎么办? :S

格雷厄姆

另外:为什么我不能'bytesPerSecond = (bytesRead / duration.Elapsed.TotalSeconds)'和移动持续时间。启动& duration.Stop进入while循环并获得准确的结果?我原本以为这会更准确吗?每个速度读取为900字节/秒,800字节/秒等。

3 个答案:

答案 0 :(得分:3)

我这样做的方式是: 保存长传输的所有字节。

然后每1秒我检查一下已经转移了多少。所以我基本上只触发代码以便在pr秒后保存速度。你的while循环将在快速网络上一秒钟内循环播放maaaaaaaaaaa。

根据网络的速度,您可能需要检查在单独的线程或功能中传输的字节数。我喜欢用Timer做这个,所以我可以轻松更新UI

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

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

你也应该对这些值进行调整,这样你就不会得到microsoft minutes个错误。我通过这样做来正常运行Timer函数:

//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.

答案 1 :(得分:2)

您和您要发送到的系统之间有许多软件和硬件层,其中一些层具有一定的缓冲空间。

当你第一次开始发送时,你可以很快地抽出数据,直到你填充这些缓冲区 - 但它实际上并没有快速到达另一端的速度!在你填满发送缓冲区之后,你只能以与它耗尽相同的速率将更多数据放入它们中,因此你看到的速率将下降到基础网络发送速率。

答案 2 :(得分:0)

所有,我认为我已经修正了我的问题,通过调整5 - 10平均变量来等待一秒钟来解释爆发,而不是最好的,但是会允许互联网自行排序并允许我捕获平滑的传输

从我的网络流量中可以看出它正在崩溃,因此代码中没有任何内容可以用不同的方式来阻止它。

在我犹豫地接受自己的答案之前,请仍然对更多答案感兴趣。