我对BT相关协议很感兴趣, 萌生了自己实现一个PT Tracker服务端的想法。 顺便学习下Koitln语言, 于是有了 https://github.com/blanexie/vxph 这个项目, 本项目使用的是 JVM17+Kotlin + Gradle + SpringBoot + Sqlite的框架组合方式。
Bep003 协议是BT协议族的最基础协议。 本篇先讲述下这个协议的内容, 在描述下本项目是怎么实现这个协议的。
Torrent文件和所有的BT协议中的内容都是使用这个编码的。 具体详细可以百度了解下
协议中的简单描述:
- 关于字符串的字符集, 十分混乱。 建议还是使用
ISO_8859_1进行编码, 中文也是先转成字节数组,在使用这个字符集编码- 字节数组的编码,协议中也没有说明, 不过通用的还是先用
ISO_8859_1编码成字符串,在使用bencode编码
文件结构分两种, 单文件结构和多文件结构
bep003中定义的内容比较少,但是下面的树形结构中内容很多, 多余的内容不用管,都是后面补充协议加上去的
├─announce:Tracker的主服务器
├─announce-list:Tracker服务器列表
├─comment:种子文件的注释
├─comment.utf-8:种子文件注释的utf-8编码
├─creation date:种子文件建立的时间,是从1970年1月1日00:00:00到现在的秒数。
├─encoding:种子文件的默认编码,比如GB2312,Big5,utf-8等
├─info:所有关于下载的文件的信息
│ ├─files:表示文件的名字
│ │ ├─length:文件的大小(Byte)
│ │ ├─path:文件的名字,在下载时不可更改
│ │ └─path.utf-8:文件名的UTF-8编码,同上
│ ├─name:推荐的文件夹名,此项可于下载时更改
│ ├─name.utf-8:推荐的文件夹名的utf-8编码,同上
│ ├─piece length:每个文件块的大小(Byte)
│ ├─pieces:文件的特征信息(将所有文件按照piece length的字节大小分成块,每块计算一个SHA1值,然后将这些值连接起来所组成)
│ ├─publisher:文件发布者的名字
│ ├─publisher-url:文件发布者的网址
│ ├─publisher-url.utf-8:文件发布者网址的utf-8编码
│ └─publisher.utf-8:文件发布者的名字的utf-8编码
└─nodes:这个字段包含一系列ip和相应端口的列表,是用于连接DHT初始node
├─announce:Tracker的主服务器
├─announce-list:Tracker服务器列表
├─comment:种子文件的注释
├─comment.utf-8:种子文件注释的utf-8编码
├─creation date:种子文件建立的时间,是从1970年1月1日00:00:00到现在的秒数。
├─encoding:种子文件的默认编码,比如GB2312,Big5,utf-8等
├─info:所有关于下载的文件的信息
│ ├─length:文件的大小(Byte)
│ ├─name:推荐的文件夹名,此项可于下载时更改
│ ├─name.utf-8:推荐的文件夹名的utf-8编码,同上
│ ├─piece length:每个文件块的大小(Byte)
│ ├─pieces:文件的特征信息(将所有文件按照piece length的字节大小分成块,每块计算一个SHA1值,然后将这些值连接起来所组成)
│ ├─publisher:文件发布者的名字
│ ├─publisher-url:文件发布者的网址
│ ├─publisher-url.utf-8:文件发布者网址的utf-8编码
│ └─publisher.utf-8:文件发布者的名字的utf-8编码
└─nodes:这个字段包含一系列ip和相应端口的列表,是用于连接DHT初始node
Tracker可以理解成BT的注册中心, 它记录各个下载客户端信息的服务,
各个客户端也可以从tracker中获取其他下载或者做种的用户。
客户端一般都是使用HTTP GET 请求来上报给tracker信息。 上报的参数如下:
约定俗成的请求路径为 /announce , 下面是一个真实请求示例: 示例中包含有很多其他的字段,不用管都是BT其他协议引入的
GET /announce?info_hash=j%25%7c%fe%12%0e%c0%9d%ee6%d5%df%03%bb%fda%cd%7b%97%b5&peer_id=-qB4510-1MTFo0SteXN2&port=22387&uploaded=0&downloaded=0&left=0&corrupt=0&key=332CA113&event=started&numwant=200&compact=1&no_peer_id=1&supportcrypto=1&redundant=0&ipv4=198.18.0.1&ipv6=2408%3a8214%3a2e11%3a8cb1%3a%3a9b8&ipv6=2408%3a8214%3a2e11%3a8cb1%3a7c27%3acac2%3a3b51%3a42fb&ipv6=2408%3a8214%3a2e11%3a8cb1%3ae0e7%3a8eb%3a4677%3a21f0

由于infoHash是一个20长度的字节数组, Qbitorrent客户端上报的infoHash字段中,SpringBoot的默认参数解析无法正确接码,于是我自定义了接口参数注解和解析方式。
也许有更好的解决方案,但是我不清楚。 希望知道的人指点。
InfoHashParam 注解定义
InfoHashRequestParamResolver 参数解析类
在这个类中会识别判断@InfoHashParam 并从URL中截取出来参数解析

装配到Spring框架中


Bep003协议还包含其它内容, 比如Peer相关的内容, 但是由于我想做的只是Tracker服务,所以文章中没有描述。
项目中使用到了SaToken作为鉴权方式, 但是由于SaToken还不支持Java17版本,于是我修改了SaToken的相关类使得兼容17。 具体内容会在下篇文章中详述。