Multithreading 如何仅使用程序可用的带宽

Multithreading 如何仅使用程序可用的带宽,multithreading,concurrency,language-agnostic,network-programming,Multithreading,Concurrency,Language Agnostic,Network Programming,我正在制作一个程序,将下载一堆不同的项目。我的语言具有廉价的并发性,所以我首先想到我可以一次下载它们。问题是。如果我尝试一次下载所有内容,用户将不得不等待所有内容,然后才能获得任何内容 假设您正在下载10个可以以7 mb/s速度下载的项目,并且您的下载速度为20 mb/s。程序应仅开始下载前三个项目,并且仅在旧项目完成且有带宽时才开始下载新项目。另外请注意,一般情况下,这些项目的下载速度不同 如果我有一些编程方法来检查网络饱和,这将很容易(只需在生成新线程之前检查其是否饱和)。正如评论中所指出的

我正在制作一个程序,将下载一堆不同的项目。我的语言具有廉价的并发性,所以我首先想到我可以一次下载它们。问题是。如果我尝试一次下载所有内容,用户将不得不等待所有内容,然后才能获得任何内容

假设您正在下载10个可以以7 mb/s速度下载的项目,并且您的下载速度为20 mb/s。程序应仅开始下载前三个项目,并且仅在旧项目完成且有带宽时才开始下载新项目。另外请注意,一般情况下,这些项目的下载速度不同


如果我有一些编程方法来检查网络饱和,这将很容易(只需在生成新线程之前检查其是否饱和)。

正如评论中所指出的,您无法很好地做到这一点,从而做出任何保证。但是,无论如何,假设你想尽力

此问题分为两部分:

  • 确定可用带宽
  • 控制正在消耗的带宽
  • 通过限制从套接字读取的速率,可以在用户空间程序中大致控制所消耗的带宽。TCP/IP堆栈将通知连接的另一端,代表您的应用程序维护的队列已满,不再发送任何内容。实现该速率限制的一种方便方法是使用

    快速令牌桶实现:

     int bucket = 0;
     start_thread({ while(transfer_in_progress) {
                        bucket += bytes_per_second_limit;
                        sleep(1);
                    });
     while(transfer_in_progress) {
        bytesread = read(socket, buffer, min(bucket, buffersize), );
        bucket -= bytesread;
     }
    
    如果
    bytes\u per\u second\u limit
    设置为可用带宽的大致值,以字节/秒表示,则应以连接允许的速度读取。如果连接速度更快,您将被限制为
    字节/秒\u限制
    。如果连接速度较慢,则
    存储桶将以与速度限制和可用带宽之差成比例的速率永远增长

    如果运行另一个线程,并密切关注
    bucket
    ,则可以观察两种情况:

  • 如果
    bucket
    始终为0,则有更多可用带宽,您可以增加
    字节/秒\u限制
    ,这可能受到您最近对可用带宽的最佳猜测(从#2)的限制。或者开始额外的下载
  • 如果
    bucket
    大于您上次查看的值,并且最后几秒钟的数据点似乎表明持续增长(可以进行线性回归;随您的便),以字节/秒表示的增长率是指为了使下载速率与可用带宽相匹配,您可以将
    字节/秒\u限制减少多少

  • 所有这一切的问题在于,无法保证带宽保持不变。线程监视
    bucket
    可能会在增加速率和限制速率之间来回反弹。我建议您在更改利率限制之前,先平均10秒或20秒。

    @PyRulez那么这不是一个简单的问题。你必须单独开始下载,直到达到上限,这意味着你必须决定达到上限意味着什么。在这一点上,你会知道你的带宽,但是知道每个项目的DL速度将是更加困难的。如果它们都来自同一台服务器,并且具有大致相同的DL速度,那么您可以对它们进行平均并进行假设,但如果它们都不同,那么这将是一个更困难的平衡行为。除非您对您周围的网络(以及其他网络用户!)有先验知识,否则这几乎是不可能的(即:您的程序无法自动测试和探测可用的网络资源)。我想一个选项可能是监控TCP连接,当延迟增加时,你应该停止生成新的下载,并等待它再次减少。但同样,你需要知道什么样的延迟被认为是正常的,什么样的延迟意味着你超过了阈值。我想说,好的替代方法是:(1)让用户给出最高速度阈值并相应地采取行动,或(2)只需让用户给出同时连接网络的数量。@PyRulez这很难,因为您的程序不是网络链接的唯一用户。有时DSL在许多设备和多个用户之间共享。即使在同一台PC中,如果用户在下载过程中开始浏览会怎么样?如果他们收到一封带有较大附件的电子邮件会怎么样?如果杀毒软件在那一刻开始自我更新怎么办?等等。网络饱和不是本地定义的指标。如果本地计算机到下一个上游节点有大量带宽,但该节点被阻塞到20Kb/s怎么办?您无法在本地解决此问题。您甚至无法远程解决此问题。网络延迟/吞吐量不是(通常)在您的控制范围内,因此您不应该尝试构建假定它们在控制范围内的系统。