BitTorrent Tracker 协议详解

概述

BitTorrent 网络内的主机依靠互相交换自身持有的资源来完成资源共享,而 Tracker 协议会告诉你哪些主机有你需要的资源。

本文将详细介绍 Tracker 协议。

基于 HTTP 的 Tracker 协议

Tracker 服务器可以使用 HTTP 协议对外提供服务,BitTorrent 客户端只需要向指定的 URL 发送 HTTP GET 请求即可。

一个常见的 Tracker URL 可能是这样的:http://tracker.example.org:80/announce。发送 GET 请求时需要附带下列查询字符串。

  • info_hash:由 .Torrent 文件中的信息计算出的 SHA-1 摘要,并使用 B 编码进行编码。
  • peer_id:BitTorrent 客户端启动时随机生成的长度为 20 个字符串。
  • ip:可选参数,表示发起请求的 客户端的 IP。一般情况下会在 Tracker 和客户端在同一主机上时使用。
  • port:BitTorrent 客户端监听的端口号,此端口号将用于接收其它 BitTorrent 客户端的传入连接。
  • uploaded:已经上传的数据总量(字节)。
  • downloaded:已经下载的数据总量(字节)。
  • left:还需要下载的数据总量(字节)。此数值不能使用参数 downloaded 计算,因为 downloaded 参数包含了那些下载了但是没有通过校验的数据。
  • event:可选参数,可能取值为 startcompletedstopped。可以分别在下载开始、下载完成和停止下载时发送。

Tracker 服务器收到 GET 请求时应该响应一个使用 B 编码进行编码的字典,如果请求成功则字典中必须包含下列两个键。

  • interval:一个数字,表示应该等待多少秒后才能重新请求本 Trakcer。
  • peers:一个由字典组成的列表,每个列表包含了提供被请求资源的 Peer 的 ID,IP 和端口。

如果请求成功,则返回经过 B 编码编码后字典,如果将其使用 JSON 表示则是下面这样。

{
    "interval": 120,
    "peers": [
        { "peer id": "xxxxxxxxxxxxxxxxxxxx", "ip": "192.168.1.1", "port": 7000 },
        { "peer id": "yyyyyyyyyyyyyyyyyyyy", "ip": "192.168.1.2", "port": 7001 }
    ]
}

如果请求失败则同样需要返回一个经过 B 编码编码后的字典,且必须包含一个名为 failure reason 的键,其内容是人类可读的错误提示信息。

由于 Tracker 的响应可能会很大,比如返回了大量的 Peer 信息,此时再使用 B 编码进行表示则会占用较大的空间。如果客户端不希望这种情况发生,可以在请求时添加一个名为 compact 的参数,并将其值设置为 1,表示建议 Tracker 返回经过紧凑的信息。如果其值为 0,则表示建议 Tracker 返回未经紧凑的信息。

所谓紧凑的信息实际就是将键 Peers 的内容转化为二进制发送。下面是一个例子。

// 紧凑前
d8:intervali:120e5:peersl7:peer id20:xxxxxxxxxxxxxxxxxxxx11:192.168.1.1i:7000ee

// 紧凑后 Peer ID 被丢弃
d8:intervali:120e5:peers6:\x1\x1\xA8\xC0\x58\x1B

基于 UDP 的 Tracker 协议

基于 HTTP 的 Tracker 协议需要维护一个 TCP 连接,但是通常 Tracker 的请求和响应都不是很大,维护 TCP 连接的代价相比较有点大,于是便有了基于 UDP 的 Tracker 协议。

下面是通信流程,IPV6 版本的类似。

Peer                                                        Tracker

Connect Request
+ 8 byte protocol_id
+ 4 byte action ( = 0 )
+ 4 byte transaction_id     ------------------------->
                                                            Connect Response
                                                            + 4 byte action ( = 0 )
                                                            + 4 byte transaction_id
                                                            + 8 byte connection_id
                            <-------------------------
IPV4 Announce Request
+ 8 byte connection_id
+ 4 byte action ( = 1 )
+ 4 byte transaction_id
+ 20 byte string info_hash
+ 20 byte string peer_id
+ 8 byte downloaded
+ 8 byte left
+ 8 byte uploaded
+ 4 byte event
+ 4 byte IP address
+ 4 byte key
+ 4 byte num_want
+ 2 byte port               ------------------------->
                                                            IPV4 Announce Response
                                                            + 4 byte action ( = 1 )
                                                            + 4 byte transaction_id
                                                            + 4 byte interval
                                                            + 4 byte leechers
                                                            + 4 byte seeders
                                                            + 4 * n byte IP address
                                                            + 2 * n byte TCP port
                            <-------------------------      + more

大多数参数都已经在 HTTP 版本中出现,此处只说明一些未出现的参数和有改动的参数。

  • transaction_id:由客户端随机生成的事务 ID,客户端使用此 ID 进行请求时,Tracker 服务器也必须使用同样的 ID 进行响应。
  • connection_id:由 Tracker 生成的连接 ID,客户端应该保存此 ID,并在后续请求中使用。Tracker 服务器也应该检查接收到的 ID 是否是预期的。
  • event:在 HTTP 版本的协议中此参数的取值为三个字符串或者空。在 UDP 版本中则不同。
    • 0 – none
    • 1 – completed
    • 2 – started
    • 3 – stopped
  • num_want:整数,表示希望获得的 peer 数量,默认为 -1
  • leechers:整数,表示“吸血者”的数量。“吸血者”指下载多而上传少的用户。
  • seeders:整数,表示”做种者“的数量。

参考资料

本文作者:ADD-SP
本文链接https://www.addesp.com/archives/5313
版权声明:本博客所有文章除特别声明外,均默认采用 CC-BY-NC-SA 4.0 许可协议。

评论

  1. 2年前
    2021-10-04 20:03:49

    一口气读完了三篇,还是有点懵~
    主要了解了什么是B编码,以及基于http和udp协议的tracker。
    平常经常用torrent和magnet,今天总算汲取了些干货了,谢谢群主和管理的科普。

发送评论 编辑评论


上一篇
下一篇