在计算机之间复制文件时的带宽限制

时间:2013-06-06 21:51:19

标签: c# file-copying bandwidth-throttling

我一直试图制作一个程序,将带宽限制的文件(压缩后)转移到同一网络上的另一台计算机上。

我需要限制其带宽以避免饱和(Robocopy的方式)。

最近,我找到了ThrottledStream类,但它似乎没有工作,因为我可以发送一个9MB限制1字节限制,它仍然几乎立即到达,所以我需要知道是否有一些误用的课程。

以下是代码:

using (FileStream originStream = inFile.OpenRead())    
using (MemoryStream compressedFile = new MemoryStream())      
using (GZipStream zippingStream = new GZipStream(compressedFile, CompressionMode.Compress))
{
    originStream.CopyTo(zippingStream); 
    using (FileStream finalDestination = File.Create(destination.FullName + "\\" + inFile.Name + ".gz"))
    {
        ThrottledStream destinationStream = new ThrottledStream(finalDestination, bpsLimit);
        byte[] buffer = new byte[bufferSize];
        int readCount = compressedFile.Read(buffer,0,bufferSize);
        while(readCount > 0)
        {
            destinationStream.Write(buffer, 0, bufferSize);
            readCount = compressedFile.Read(buffer, 0, bufferSize);
        }
    }
}

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:1)

您链接的ThrottledStream类使用延迟计算来确定在执行当前写入之前等待的时间。此延迟基于在当前写入之前发送的数据量以及已经过了多长时间。一旦延迟期过去,它就会将整个缓冲区写入一个块中。

这个问题是它不会对在特定写操作中写入的缓冲区的大小进行任何检查。如果要求它将吞吐量限制为每秒1个字节,则使用20MB缓冲区调用Write方法,它将立即写入整个20MB。如果你然后尝试写另一个2字节长的数据块,它将在写入这两个字节之前等待很长时间(20 * 2 ^ 20秒)。

为了让ThrottledStream课程更顺畅地工作,您必须使用非常小的数据块调用Write。每个块仍将立即写入,但写入操作之间的延迟将更小,吞吐量将更加均匀。

在您的代码中,您使用名为bufferSize的变量来确定内部循环中每次读取/写入要处理的字节数。尝试将bufferSize设置为256,这将导致更多的读写操作,但会使ThrottledStream有机会实际引入一些延迟。

如果将bufferSize设置为与bpsLimit相同,则应该看到每秒完成一次写操作。您设置的bufferSize越小,每秒获得的写操作就越多,平滑的带宽限制将起作用。

通常我们希望在每个操作中尽可能多地处理缓冲区以减少开销,但在这种情况下,您明确地尝试添加开销来减慢速度:)