4

我正在用 C# 编写一个应用程序,它使用多个连接到多个服务器同时下载(在不同的线程中),我希望能够限制使用的带宽。

对于单个连接,解决方案很简单;我会使用此处发布的解决方案:http: //www.codeproject.com/KB/IP/Bandwidth_throttling.aspx ,它计算单个连接的睡眠时间。

我想知道对多个连接执行此操作的最佳方法是什么。

使用上面发布的 ThrottledStream 并在连接之间平均分配带宽(比如 2MB/秒)是不对的,如果我有 3 个非常慢的连接和 1 个非常快的连接,它们都将被限制为 512kb/秒,所以快速的一个不会超过 512kb/sec,而其他 3 个甚至都不会。

我认为首选的解决方案是只限制最快的连接,以便最佳地使用较慢的连接。

有没有人对此有任何经验,示例代码或任何建议?

4

5 回答 5

3

如果是我,我会先将带宽要求分成 N 块,其中 N 是并发连接数。接下来,我将监控每个连接的性能并根据需要进行调整。首先,我会确定以我设置的最大速度运行的任何连接。如果需要,这些连接将成为提高速度的候选者。接下来,我将确定那些不符合我提出的带宽限制的连接(成绩不佳者)。这样就很容易总结后一组的不足之处。您将获取该数字,除以以最高速度执行的连接数并进行调整。

允许的总带宽:100KB/秒
连接数:5
初始每个连接限制:20KB/秒

实际结果:
连接 1:10KB/秒
连接 2:5KB/秒
连接 3:20KB/秒
连接 3:20KB/秒
连接 3:20KB/秒

总短:15KB/秒

新的每连接限制:
连接 1:10KB/秒
连接 2:5KB/秒
连接 3:25KB/秒
连接 3:25KB/秒
连接 3:25KB/秒

然后,您将每隔一段时间对其进行监控。

于 2009-05-18T20:17:31.723 回答
2

在我的脑海中,我会得到一个收集器对象/类,它从每个流中按顺序提取,收集器在适当的时候处于休眠状态(可能通过移动平均比较)。如果一个比另一个慢,这将平衡您的流以允许实现完整的带宽限制......您将轮询拉,发现它是空的,然后在睡觉前拉下一个流。

由于您的收集器受提取的聚合数据/时间的限制,您将获得正确的客户端带宽。

于 2009-05-18T20:08:27.327 回答
0

我也有同样的问题。我正在尝试 VS2010 Pro,并且我制作了小型家庭项目,我正在同时下载多个文件(10-50)并且我想限制所有文件的带宽。我找到了这个帖子,但我真的看不到解决方案,所以我自己尝试了。

我所做的是,我创建了一个非常简单的 DownloadLimiter 类。每次下载器想要下载一个块时(例如,就在 InputStream.Read() 之前),它必须向 DownloadLimiter 询问带宽。它有一个变量,它有一个限制,例如 50 000(如 bytesPerSecond)和 availableBandwidthPerSecond,它随着每个 ask() 的处理和返回而减少。

它还包含一个 Timer,它每 1000 毫秒将 availableBandwidthPerSecond 重置为限制。

ask() 方法被锁定,因此如果当前没有任何可用带宽,它只会循环并休眠一段时间,直到计时器重置可用带宽。

然而,它完美地工作。有一个问题。假设您的连接速度非常快(100 兆位),并且您将限制设置为 200kb。如果您下载一个文件(从类似的快速连接),那么您将在 x 毫秒内达到 100 兆比特的峰值,然后它将等到可用带宽被重置。这将一直持续到文件完成。平均下载速度将相当均匀,但如果您查看带宽图,它每秒都会出现峰值。我猜想 ThrottledStream 的发布链接与峰值的工作方式相同。

我不知道上面的文字是否对您有所帮助...如果有人有兴趣,我可以将代码发布在某处供您阅读。一些优化(如果你愿意的话)也会很好,因为我还不太熟悉线程。:)

于 2010-04-20T22:25:12.327 回答
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
于 2009-07-11T22:10:33.763 回答
0

稍加调整,您就可以使用您在第一篇文章中链接的类,将 Throttle 和 Reset 放在静态类中。

于 2011-04-22T04:02:15.457 回答