概述
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:可选参数,可能取值为
start
、completed
和stopped
。可以分别在下载开始、下载完成和停止下载时发送。
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:整数,表示”做种者“的数量。
一口气读完了三篇,还是有点懵~
主要了解了什么是B编码,以及基于http和udp协议的tracker。
平常经常用torrent和magnet,今天总算汲取了些干货了,谢谢群主和管理的科普。
B 编码参考这篇:https://www.codeclip.com/4096.html