WebSeed – 基于 HTTP/FTP 做种的 BitTorrent 技术

摘要

通过在下载过程中使用 HTTP 或 FTP 服务器向节点发送额外的数据来增加下载速度,从而减少 BitTorrent 下载中可能出现的下载停滞情况。

原理

很多提供 BitTorrent 下载链接的网站也会同时提供相同文件的 HTTP 或 FTP URL。这些 URL 所指向的文件是完全相同的。利用 WebSeeding 技术的 BitTorrent 客户端可以从任意一种来源(即 BitTorrent 和 HTTP 或 FTP)下载文件,将下载到的数据块组装成为一个完整的文件。HTTP 或 FTP 服务器充当着一个始终处于未限速状态的“种子”,即它可以不间断地提供文件的数据块,以加速文件的下载。

优势

每个 BitTorrent 下载都有一些开放下载端口的源,也就是种子,任何人都可以从这些源开始下载。

对于不能识别元数据添加的客户端,这种新方法不会破坏或更改任何内容。

不支持 HTTP/FTP 种子的 BitTorrent 客户端仍然可以通过其他支持 HTTP/FTP 的同伴来共享数据块。

无需更改元数据。下载管理工具通常可以为一个文件添加多个 HTTP/FTP 镜像网址,用户只需单击网页上多个链接并识别相同的文件名即可。

大家对 HTTP/FTP 服务器及其协议非常熟悉。

这种新方法已经在多个 BitTorrent 客户端中实现,如 IMFile、GetRight、Mainline、uTorrent、Azureus 和 libTorrent。

只需要在 BitTorrent 客户端中进行少量更改,并且不需要更改 Tracker、HTTP 或 FTP 服务器。在 HTTP 或 FTP 服务器上也不需要使用脚本。

由于许多常见的客户端已经支持此功能(特别是 IMFile 客户端),因此使用公司或个人现有的 HTTP/FTP 服务器完全可以进行 BitTorrent 下载的种子发布。

元数据扩展

在 BitTorrent 元数据文件的主要区域中,而不是 “info” 部分的一部分,将会有一个新键 “url-list”。该键将引用一个或多个 URL 地址列表,并包含可以检索种子数据的网址列表。如果客户端无法使用此键,则可以安全地忽略它。

例:

      d 8:announce27:http:tracker.com/announce
      8:url-list26:http:mirror.com/file.exe
      4:info…

如果 “url-list” URL 以斜杠 “/” 结尾,则客户端必须添加种子文件名来生成完整的 URL。这样可以让 .torrent 生成器将此字段同等对待单文件和多文件种子。

多文件种子

在下载多文件种子时,BitTorrent 客户端通常会使用种子文件中 “info” 部分中的 “name” 字段作为根目录,并使用 “path/file” 字段来指定在该根目录下的文件路径和名称。但是,在这个例子中,种子文件的 “url-list” 字段被用作根目录,因此客户端需要将 “name” 和 “path/file” 添加到该根目录中,以创建请求的 URL。

例如,

... 8:url-list22:http://mirror.com/pub/ 4:infod5:filesld6:lengthi949e4:pathl10:Readme.txte e4:name7:michael

在这个例子中,客户端需要将 “name” 设置为 “michael”,并将 “path/file” 中的 “Readme.txt” 文件添加到 http://mirror.com/pub/ 根目录中,以生成下载请求的 URL 。客户端将使用上述步骤生成的根目录、文件路径和文件名称,将它们拼接起来,生成一个完整的下载请求 URL:http://mirror.com/pub/michael/Readme.txt。

客户端实现概述

首先,客户端应该忽略它不认识的协议,因为如果尝试连接这样的协议可能会导致错误。例如,一个客户端可能只支持 HTTP 而不支持 FTP,或者反过来。

其次,HTTP 和 FTP 协议都是流式传输的协议,而没有 BitTorrent 中所谓的数据块的概念。这意味着当使用 HTTP 或 FTP 下载时,会出现很多数据空隙,因为无法像 BitTorrent 那样对文件进行分块下载。

为了解决这个问题,对实现中的“最稀缺优先”块选择方法进行了修改,使得下载的文件中存在更多的数据空隙,这样 HTTP 和 FTP 线程就可以从这些空隙开始下载,直到填满整个空隙。可以使用 HTTP 的字节范围请求功能来请求单个块,但这可能会被服务器记录下来,并被误认为是针对该服务器的 DoS 攻击。

客户端实现注意事项

为了让 HTTP 和 FTP 连接更好地填充文件中的很多连续块,BitTorrent 的标准算法进行了一些更改。

空隙的定义

空隙指的是客户端没有的多个相邻块所组成的空间。在这个例子中,假设有一个位域”YYnnnnYnnY”,其中 Y 表示客户端拥有的块,n 表示客户端没有的块。那么,在该位域中就存在两个空隙,分别是长度为 4 和长度为 2 的相邻未下载的块组成的空间。

下载块的选择

最主要的变化是下载块的选择,如果所有缺失块的稀有度相似,那么在请求一个块时,最好从长度为 2 的间隙中选择一个块开始下载。而在任何间隙中,最好从结尾开始填充(即优先选择最高编号的块)。因此,在给定的位域 “YYnnnnYnnY” 中,如果缺失块的稀有度相似,则最好选择 “# pieces YYnnnnY##Y” 中的一个块进行下载,其中最佳的选择是选择块 “$ YYnnnnYn$Y”。

这些块选择策略可以最大程度地利用 HTTP/FTP 连接的连续数据下载。这样,HTTP/FTP 连接可以从间隔的开头开始下载,并在连接到客户端已有的块之前尽可能多地下载数据。

更改块选取策略

将下载块选取策略从原来的“先选最稀有的”修改为“优先选取与已完成块距离最远且相对稀有的”。

最罕见且最大间隔的块

首先找到当前所有未下载块中出现频率最少的块,即 PRWBG(Pretty Rare With Biggest Gap – 最罕见且最大间隔的块),假设它距离已经下载完成的另一块的距离为 D。

对于其他未下载块,如果它们与已下载块的距离小于 D,则认为它们比 PRWBG 更罕见,因此被标记为 “罕见-X”(其中 X 是一个常数,等于“对等方数量减1的平方根”)。

相反地,如果某个未下载块与已下载块之间的距离大于 D,则认为它可能比 PRWBG 更容易获得,并被标记为 “罕见+X”,以备可能选择作为下一个下载块。

如果当前最稀有的一块只有 3 个节点拥有,那么通常的算法会选择另外两个节点也有的拼。但是,如果使用修改后的算法,当一块距离完整文件的距离小于当前最稀有块的间隔时,只需要有1个节点拥有这一块即可选择它。

如果间隔更大且该块的“稀有程度”与通常的“稀有-1”相同,那么将选择这一块(因此,如果间隔更大,则会选择具有 2 或 3 个节点拥有的块)。

因此,在给定的”YYnnn1Yn2Y”情况下,除非 1 比 2 更稀有,否则最好选择 2。

伪代码逻辑:

      X = sqrt(Peers) - 1;
      Gap = 0;
      CurGap = 0;
      CurRarest = MaxPieces+1;
      for (i=0; i<MaxPieces; i++) {
          if (IDoNotHavePiece(i)) {
              Gap++;
              if (PeerHasPiece(i)) {
                  PieceRareness = NumberOfPeersWithThePiece();
                  if (PieceRareness<(CurRarest-X) ||
                      (PieceRareness<=(CurRarest+X) && Gap>CurGap)) {
                      CurRarest = PieceRareness;
                      CurGap = Gap;
                      NextPiece = i;
                  }
              }
          } else {
              Gap = 0;
          }
      }

填补空隙

当一个文件已经完成了 50% 以上时,使用不同的方法随机选择下载块。(在 50% 以上,你应该有大量其他节点想要下载的块。)

每隔几个块,它会选择距离完整文件最近的块,忽略所有的稀有度。例如,在位域 “YYnnnnYnnY” 中,它将选择块#”YYnnnnYn#Y”。这有助于填补小缺口。

客户端可以选择是否执行此步骤,如果实现此功能,还可以使用另一个文件完成百分比。

伪代码逻辑:

      Gap = 0;
      Piece = -1;
      CurGap = MaxPieces+1;
      for (i=0; i<MaxPieces; i++) {
          if (IDoNotHavePiece(i)) {
              Gap++;
              if (PeerHasPiece(i)) {
                  Piece = i;
              }
          } else {----
              if (Gap<CurGap && Gap>0 && Piece!=-1) {
                  CurGap = Gap;
                  NextPiece = Piece;
              }
              Gap = 0;
              Piece = -1;
          }
      }

HTTP 和 FTP 优化

对于 HTTP/FTP 协议或服务器本身无需进行修改。

如果客户端知道 HTTP/FTP 下载是 BitTorrent 下载的一部分,则最好在第一次连接时随机选择文件中的某个位置开始下载。这样,它获得的第一批 HTTP 数据块更有可能对 BitTorrent 节点进行共享。

如果在启动 HTTP/FTP 连接时已经存在一个正在进行的 BitTorrent 下载,则 HTTP/FTP 应从最大空隙的开头开始。对于位域“YYnnnnYnnY”,它应该从#号开始:“YY#nnnYnnY”。

如果成功从 HTTP/FTP 服务器下载了一块数据块,但 SHA 校验和不匹配,则必须关闭连接并丢弃该 URL。

如果客户端收到“忙”回复,则无需放弃 HTTP 或 FTP 服务器的 URL。

多文件种子

当使用 HTTP/FTP 服务器进行多文件种子下载时,需要额外的选择算法来优化下载效率。

对于大型文件,客户端可以选择 BitTorrent 块以优化下载速度,从而能够从 HTTP/FTP 服务器完整地下载整个文件。

对于包含小文件的种子,可能需要进行多个 HTTP/FTP 传输才能完成一个块的下载。在这种情况下,使用 BitTorrent 进行传输可能更为合适。例如,如果有 100 个 1KB 的文件,假设块大小为 32KB,则需要进行 100 个 HTTP/FTP 传输才能完成文件的下载,但只需要 4 个 BitTorrent 块请求。

因此,将小文件给予 BitTorrent 块选择更高的优先级,将大文件给予 HTTP/FTP 更高的优先级,可以有效提高下载效率。

另一种可能的客户端实现

如果客户端只支持 HTTP 而不支持 FTP,则可以利用 HTTP 的字节范围请求功能,但每次请求多个块。

将多个块视为单个集合,并向 HTTP 服务器发送单个字节范围请求。这将减少 HTTP 连接的数量,并且对于客户端可能会有很好的效果。

可以将块视为 10、50 或 100 个块。如果按照这种方式进行处理,”Pieces Per Block” 可以选择为 MaxPieces/20,因此每次请求约为文件的 5%。

不建议的客户端实现

客户端可以简单地使用 HTTP 字节范围请求来请求单个片段。但是,一些服务器管理员可能不会喜欢这种实现方式,因为针对单个文件将会在他们的日志中产生数百或数千个请求。有些人甚至可能认为这是对他们的拒绝服务攻击。

其他协议内容

可能用于下载数据的协议。尽管在上文中列出了 HTTP/FTP 作为用于种子分享的协议,但是客户端可以使用任何允许下载数据的协议。例如 HTTPS、FTPS 或 SFTP 等协议也可以被使用,但可能不是所有客户端都支持。

RTSP 和 MMS 等协议也有可能被使用。甚至还可以使用 Usenet 的 NNTP 协议进行下载。

其他协议可能存在其他问题,例如不允许从文件的任意位置开始下载。

客户端可以选择仅实现 HTTP 或 FTP 协议中的一个而不是两者同时实现。

参考链接

  • http://www.bittorrent.org/beps/bep_0019.html

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注