我正在用C#编写一个应用程序,它使用多个服务器的多个连接同时下载(在不同的线程中), 我希望能够限制使用的带宽。
对于单一连接,解决方案很简单;我会使用此处发布的解决方案:http://www.codeproject.com/KB/IP/Bandwidth_throttling.aspx 它计算单个连接的睡眠时间。
我想知道为多个连接执行此操作的最佳方法是什么。
使用上面发布的ThrottledStream并在连接之间均匀划分带宽(比如2MB /秒)是不对的,如果我有3个非常慢的连接和1个非常快的连接它们都被限制为512kb /秒,所以快速的不会超过512kb /秒而另外3个甚至不会这样。
我认为首选的解决方案是仅限最快的连接,以便最佳地使用较慢的连接。
有没有人对此,示例代码或任何建议有任何经验?
答案 0 :(得分:3)
如果是我,我首先将带宽需求划分为N个,其中N是并发连接数。接下来,我将监视每个连接的性能并根据需要进行调整。首先,我将确定以我设置的最大速度运行的任何连接。如果需要,这些连接将成为提高速度的候选者。接下来,我将确定那些不符合我提出的带宽限制的连接(后进生者)。然后很容易总结后一组的短缺情况。您可以将该数字除以以最高速度执行的连接数并进行调整。
Total Bandwidth Allowed: 100KB/Sec Connections : 5 Initial per-connection limit: 20KB/sec Actual Results: Connection 1: 10KB/sec Connection 2: 5KB/sec Connection 3: 20KB/sec Connection 3: 20KB/sec Connection 3: 20KB/sec Total Short: 15KB/sec New Per-Connection Limits: Connection 1: 10KB/sec Connection 2: 5KB/sec Connection 3: 25KB/sec Connection 3: 25KB/sec Connection 3: 25KB/sec
然后你会在某个时间间隔对此进行监控。
答案 1 :(得分:2)
离开我的头顶,我会得到一个收集器对象/类,它按顺序从每个流中拉出,收集器在适当时睡觉(可能通过移动平均线比较)。这将平衡您的流,以便在一个比另一个慢的情况下实现全带宽限制...您将轮询以拉出,找到它为空,并在睡觉前拉下一个流。
由于您的收集器受到总数据拉/时间的限制,因此您将获得正确的客户端带宽。
答案 2 :(得分:0)
上面的总短数实际上是25kb /秒,但不是将连接分成组,而是按速度排序并循环遍历它们。从总带宽开始,将新带宽设置为(剩余带宽/剩余计数)。这将保持5k和10k连接的限制,以防它们加速。您可以检查分配的带宽,但是您可以更正它。
List<Connection> connections = GetConnections();
connections.Sort(); // sorts by Speed
bandwidth = 100000;
for (int i = 0; i < connections.Count; i++)
{
Connection cnn = connections[i];
cnn.SpeedLimit = bandwidth / (connections.Count - i);
bandwidth -= Math.Min(cnn.Speed, cnn.SpeedLimit);
}
(start with all connections SpeedLimit set to 20000 bytes/sec)
Speed bandwidth SpeedLimit
5000 100000 20000
10000 95000 23750
20000 85000 28333
20000 65000 32500
20000 45000 45000
连接的总速度限制为149583,因此如果慢速加速,你可以超过限制,但如果你每秒调整限制,它应该非常接近。
连接速度变为:5000,10000,28333,21000,45000,所以我们实际下载了109,333字节,但我们会再次调整。除45k之外的所有连接都达到了可能的限制:
Speed bandwidth SpeedLimit
5000 100000 20000
10000 95000 23750
21000 85000 28333
28333 64000 32000
45000 35667 35667
新的速度将分别为5000,10000,21000,28333,35667,100k
Speed bandwidth SpeedLimit
5000 100000 20000
10000 95000 23750
21000 85000 28333
28333 64000 32000
35667 35667 35667
现在让我们假设5k连接速度高达20k:
Speed bandwidth SpeedLimit
10000 100000 20000
20000 90000 22500
21000 70000 23333
28333 49000 24500
35667 20667 20667
答案 3 :(得分:0)
我有同样的问题。我正在尝试VS2010 Pro,我已经制作了小型家庭项目,我同时下载多个文件(10-50),我想限制所有的带宽。我找到了这个帖子,但我找不到解决方案,所以我自己试了一下。
我做的是,我创建了一个真正简单的DownloadLimiter类。每次下载者想要下载一个块(比如,就在InputStream.Read()之前),它必须向DownloadLimiter询问带宽。它有一个包含限制的变量,例如50 000(如bytesPerSecond)和availableBandwidthPerSecond,它们在处理和返回每个ask()时会减少。
它还包含一个Timer,它将availableBandwidthPerSecond重置为每1000ms的限制。
ask()方法被锁定,所以如果当前没有剩余可用带宽,它只会循环并暂停一段时间,直到Timer重置可用带宽为止。
然而,它完美无缺。有一个问题。假设你有一个非常快速的连接(100兆位),你将限制设置为200kb。如果您下载一个文件(来自类似的快速连接),那么您将以100兆比特的峰值达到x毫秒,然后它将等待可用带宽重置。这将一直持续到文件完成。平均下载速度相当均匀,但如果你看一个带宽图,它会每秒都有峰值。 我想ThrottledStream发布的链接与峰值的工作方式相同。我不知道上面的文字是否对你有帮助......如果有人有兴趣,我可以在某处发布代码供你阅读。对于一些优化(如果你想)也会很好,因为我还不熟悉线程。 :)
答案 4 :(得分:0)
通过一些调整,您可以使用您在第一篇文章中链接的课程,将Throttle和Reset放在静态课程中。