前序文章:
前文内容回顾:
在 Peers 通讯分析部分,通过描述较难理解实际传输细节,本文将在前述文章基础上,通过一个实例来对 Peers 数据传输内容进行详细分析。
51045
。通过下述 Python 脚本生成大小为 256 KB 的 bin 文件
with open("test.bin", "wb") as file:
for j in range(1024):
for i in range(0, 256):
file.write(i.to_bytes(1, byteorder='big'))
计算其 SHA1 值,完成元数据文件
{
"announce": "http://10.0.150.202:6969/announce",
"info": {
"length": 262144,
"name": "test.bin",
"piecelength": 33554432,
"pieces": b"7\xefwio\xc2U\xbfS\xb4\xcd\xd0\x14\xb2#go-\xc8\xb",
"private": 1
}
}
为了避免 Transmission 在匿名网络上汇报数据为测试带来不确定性,此处增加了前文暂未提及的 私有
标记 private
,Transmission 将会识别这一标记,并不再将该任务通过 DHT、PeX、LSD 等网络请求和传输,若有机会可以在后续文章中进行具体分析包括其在内的拓展内容。
其实也可以直接在设置中关闭 Transmission 的匿名节点交换连接
对 info 段字典进行 Becode 编码,计算 SHA 1,得到该元数据的信息哈希:
1ae5136ee599a6d67913d5ab6a44a4efdfa681e4
将元数据文件导入 Transmission 中,校验并开始下载(做种):
Tracker 请求在前文中已经有了具体描述和样例分析,再次不再重复,直接进入 Peers 数据传输内容。
首先需要生成 Peer ID,这是一个 20 字节随机字符串,目前市面上众多下载器均使用 -标识-随机内容
在 Peer ID 中加入自己下载器的标识,如 qBittorrent 的 Peer ID 以 -QB{版本号}- 作为起始,测试可以任意选择。本文选用 -Qcloud-thisisrandom
为 Peer ID。
通过 Sockit 向 Transmission 端口发起 TCP 连接,并发送握手信息,握手信息十六进制编码如下:
13 42 69 74 54 6F 72 72 65 6E 74 20 70 72 6F 74 6F 63 6F 6C 00 00 00 00 00 00 00 00 1A E5 13 6E E5 99 A6 D6 79 13 D5 AB 6A 44 A4 EF DF A6 81 E4 2D 51 63 6C 6F 75 64 2D 74 68 69 73 69 73 72 61 6E 64 6F 6D
具体如下:
-Qcloud-thisisrandom
的 ASCII 编码发送响应后,收到 Transmission 回应的握手信息:
13 42 69 74 54 6F 72 72 65 6E 74 20 70 72 6F 74 6F 63 6F 6C 00 00 00 00 00 10 00 04 1A E5 13 6E E5 99 A6 D6 79 13 D5 AB 6A 44 A4 EF DF A6 81 E4 2D 54 52 34 30 34 30 2D 68 70 66 63 6D 76 64 74 6F 79 38 6D
上图在断开连接前,还收到了 Transmission 发的 bitfield、unchock 数据,后面再进行分析,先看收到的前 68 字节的握手回应:
-TR4040-hpfcmvdtoy8m
的 ASCII 编码,可知对本数据,Transmission 的 Peer ID 为 -TR4040-hpfcmvdtoy8m在握手完成后,双方应该交换 BitField,上述握手之后,已经收到了 Transmission 的 BitField 数据:
00 00 00 02 05 80
在握手完成后,所有整型数据均为 4 字节大端位编码,数据收个数为消息长度,即 00 00 00 02 代表该消息长度为 2 字节,消息内容第一位为类型标记 05 对应 Bitfield(回顾Bittorrent 协议浅析(二)Tracker 和 对等节点),根据信息中的文件大小和分片大小可知,该内容只有 1 个分片,故分片位表只有 1 位,其他为填充,收到的数据 0x80 即 1000 0000 B,可知 Transmission 告知其拥有第一分片的内容。
特别需要注意的是,部分下载器在 BitField 宣告过程中会故意将部分位置 0,然后通过 Have
消息告知其拥有该分片。
Transmission 还发送了 Unchock 消息
[00 00 00 01 01]
同理,该消息长度为 1 字节,类型为 Unchock,不需要其他内容。收到该消息表明 Transmission 已经解锁了上传,此时,在 Transmission 中查看资源属性,可以看到:
此时,向其发送 Interested 信息,来表明对其拥有的数据分片“感兴趣”,发送的 Interested 数据仅有一个字节表明类型,如下:
[00 00 00 01 02]
在一方 Interested 且另一方 Unchock 情况下,前者请求数据后者就会将数据进行传输,对应的,Transmission 中状态如下:
一个 BitTorrent 分片可能较大,并不适合一次传输一整个分片,所以在传输过程中又将其进行再次切分传输,每次请求分片数据需要带偏移量和请求数据的大小。
在准备好上传后便可进行传输数据的请求,Request 消息包括了 分片索引、偏移量和请求传输的数据长度,这三个内容均为整数,故 Request 消息的大小应为 13 字节(0x0D),如下四条数据即为四个 Request 请求:
[00 00 00 0D 06 00 00 00 00 00 00 00 00 00 00 10 00]
[00 00 00 0D 06 00 00 00 00 00 00 10 00 00 00 10 00]
[00 00 00 0D 06 00 00 00 00 00 00 20 00 00 00 10 00]
[00 00 00 0D 06 00 00 00 00 00 00 30 00 00 00 10 00]
这四条数据均请求了索引为 0 的分片,偏移地址分别为 0x00,0x1000,0x2000,0x3000,每个请求数据传输的大小为 4096 字节(0x1000)。
发送 Request 消息后,对方会通过 Piece 消息返回数据,偏移量和数据直接跟在请求长度和标记后,如下:
以第一个 Piece 响应为例,
[00 00 10 09 07 00 00 00 00 00 00 00 00 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 ...
该数据长度为 4105 (0x1009)字节, 类型为 Piece (07),偏移量为 0 (0x0),后续即为数据,与生成的 bin 文件数据内容一致。
对于请求过的内容可以再次请求,也可以设置不同的偏移值,如下:
通过不断请求分块即可完成分片,完成所有分片即可根据元数据中的 Info 部分内容还原原始文件,对于多文件的 Torrent,可以通过计算每一个文件所处的分片和偏移量来单独获取某个文件。
在完成一个分片下载后,通过 Have
消息通知所有就该数据建立的连接,Have 消息内容除了类型标记外需要附加整数形的分片索引。
通知对方节点取消上传的 Cancel 消息的结构和 Request 消息一致。
一个优秀的 BitTorrent 用户应该遵守规则、促进共享,不分发恶意软件,不滥用应是基本规范。
本文目的是通过简单的实例来分析解释 BitTorrent 写一下节点之间的数据传输内容,出于篇幅、实现难度和详略考虑,并没有涉及监听本地端口和为其他节点提供上传的内容。在实际社区当中下载者在完成下载后立即中断上传这样的行为被称之为“Hit and Run”, 是 BitTorrent 社区中的一个负面行为,在此明确表示反对。
BitTorrent 的基础协议(BEP 0003)分析到这里就结束了,基于这些内容,已经可以充分了解 BitTorrent 的基础并据此构筑很多工具了,在后续的文章中(也许),将会选择部分拓展协议进行分析,如果有了后续的文章,链接会放在这里:
最后,本文参加的征文活动广告:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。