前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Bittorrent 协议浅析(三)对等数据传输实例

Bittorrent 协议浅析(三)对等数据传输实例

原创
作者头像
青橙.
修改2023-09-30 08:11:25
5040
修改2023-09-30 08:11:25
举报
文章被收录于专栏:橙、橙、

0. 回顾

前序文章:

前文内容回顾:

  • BitTorrent 是一种用于分发文件的协议,元数据文件采用 bencode 编码,分片进行 SHA-1 哈希计算比对,并介绍元数据文件数据结构
  • Tracker Get 请求分析和实例
  • Peers 通讯分析

在 Peers 通讯分析部分,通过描述较难理解实际传输细节,本文将在前述文章基础上,通过一个实例来对 Peers 数据传输内容进行详细分析。

1. 数据传输实例

环境

  1. 使用 Sockit 工具进行 TCP 数据收发,Sockit 是一个基于 C++ 的开源工具,详细:https://github.com/sinpolib/sokithttp://code.google.com/p/sokit/
  2. 使用 Transmission 4.0.4 版本作为对端下载器,提前下载、安装和配置,随机选择并设置监听端口,在本文中,端口为 51045

准备测试文件及元数据文件

通过下述 Python 脚本生成大小为 256 KB 的 bin 文件

代码语言:python
复制
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 值,完成元数据文件

代码语言:json
复制
{
    "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,得到该元数据的信息哈希:

代码语言:text
复制
1ae5136ee599a6d67913d5ab6a44a4efdfa681e4

将元数据文件导入 Transmission 中,校验并开始下载(做种):

Transmission 导入
Transmission 导入

建立连接、握手

Tracker 请求在前文中已经有了具体描述和样例分析,再次不再重复,直接进入 Peers 数据传输内容。

首先需要生成 Peer ID,这是一个 20 字节随机字符串,目前市面上众多下载器均使用 -标识-随机内容 在 Peer ID 中加入自己下载器的标识,如 qBittorrent 的 Peer ID 以 -QB{版本号}- 作为起始,测试可以任意选择。本文选用 -Qcloud-thisisrandom 为 Peer ID。

通过 Sockit 向 Transmission 端口发起 TCP 连接,并发送握手信息,握手信息十六进制编码如下:

代码语言:text
复制
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

具体如下:

  • 0x13 (19)协议长度,固定为19
  • 42 69 74 54 6F 72 72 65 6E 74 20 70 72 6F 74 6F 63 6F 6C Bittorrnet protocol 字符串,协议
  • 00 00 00 00 00 00 00 00 拓展位,请求不使用任何拓展,全部设置为 0,
  • 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 Peer ID,-Qcloud-thisisrandom 的 ASCII 编码

发送响应后,收到 Transmission 回应的握手信息:

代码语言:text
复制
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 字节的握手回应:

  • 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 拓展预留,Transmission 宣告了支持的拓展,但由于发起握手并没有使用,所以在本次连接中拓展将不会生效
  • 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 Transmission提供的 Peer ID ,本文过程忽略与 Tracker 返回的节点列表进行比对的内容,-TR4040-hpfcmvdtoy8m 的 ASCII 编码,可知对本数据,Transmission 的 Peer ID 为 -TR4040-hpfcmvdtoy8m

Bitfield,Unchock,Interested

在握手完成后,双方应该交换 BitField,上述握手之后,已经收到了 Transmission 的 BitField 数据:

代码语言:text
复制
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 消息

Transmission Unchock 消息
Transmission Unchock 消息
代码语言:txt
复制
[00 00 00 01 01]

同理,该消息长度为 1 字节,类型为 Unchock,不需要其他内容。收到该消息表明 Transmission 已经解锁了上传,此时,在 Transmission 中查看资源属性,可以看到:

 Transmission 中的资源属性
Transmission 中的资源属性

此时,向其发送 Interested 信息,来表明对其拥有的数据分片“感兴趣”,发送的 Interested 数据仅有一个字节表明类型,如下:

代码语言:text
复制
[00 00 00 01 02]

在一方 Interested 且另一方 Unchock 情况下,前者请求数据后者就会将数据进行传输,对应的,Transmission 中状态如下:

可以传输数据
可以传输数据

Request 和 Piece

一个 BitTorrent 分片可能较大,并不适合一次传输一整个分片,所以在传输过程中又将其进行再次切分传输,每次请求分片数据需要带偏移量和请求数据的大小。

在准备好上传后便可进行传输数据的请求,Request 消息包括了 分片索引、偏移量和请求传输的数据长度,这三个内容均为整数,故 Request 消息的大小应为 13 字节(0x0D),如下四条数据即为四个 Request 请求:

代码语言:txt
复制
[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 消息返回数据,偏移量和数据直接跟在请求长度和标记后,如下:

Request 和 Piece 响应
Request 和 Piece 响应

以第一个 Piece 响应为例,

代码语言:text
复制
[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,Cancel,Request)

在完成一个分片下载后,通过 Have 消息通知所有就该数据建立的连接,Have 消息内容除了类型标记外需要附加整数形的分片索引。

通知对方节点取消上传的 Cancel 消息的结构和 Request 消息一致。

2. 成为优秀的 BitTorrent 用户

一个优秀的 BitTorrent 用户应该遵守规则、促进共享,不分发恶意软件,不滥用应是基本规范。

本文目的是通过简单的实例来分析解释 BitTorrent 写一下节点之间的数据传输内容,出于篇幅、实现难度和详略考虑,并没有涉及监听本地端口和为其他节点提供上传的内容。在实际社区当中下载者在完成下载后立即中断上传这样的行为被称之为“Hit and Run”, 是 BitTorrent 社区中的一个负面行为,在此明确表示反对。

BitTorrent 的基础协议(BEP 0003)分析到这里就结束了,基于这些内容,已经可以充分了解 BitTorrent 的基础并据此构筑很多工具了,在后续的文章中(也许),将会选择部分拓展协议进行分析,如果有了后续的文章,链接会放在这里:

最后,本文参加的征文活动广告:

我正在参与2023腾讯技术创作特训营第二期有奖征文,瓜分万元奖池和键盘手表

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0. 回顾
  • 1. 数据传输实例
    • 环境
      • 准备测试文件及元数据文件
        • 建立连接、握手
          • Bitfield,Unchock,Interested
            • Request 和 Piece
              • 其他(Have,Cancel,Request)
              • 2. 成为优秀的 BitTorrent 用户
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档