PT 站
前言
PT(Private Tracker)是一种改良自 BitTorrent 协定的 P2P 下载方式,“Private Tracker”指私有种子服务器。与 BT 最大的不同点分别为可进行私密范围下载,及可统计每个用户的上载及下载量。
PT 站的架构
NexusPHP
简介
根据其代码中的介绍(aboutnexus.php 页面)来看:
NexusPHP 由来自浙江大学的 Nexus 团队发起并开发完成。主要是提供一个完整的、有序的、重视用户信誉和知识的资源分享社区的解决方案,是一个 PT(Private Tracker,即私有的 Tracker 服务器,是 BT 下载的一种)开源软件。

(当然也有人和我说,这是某浙大生毕业设计作品 Orz)
虽然一遍一遍的在群里鄙视着 NexusPHP 的垃圾代码,但不得不承认就目前来看国内 PT 圈依然在大量使用 NP(这里应该不用做详细数据统计了吧 2333)。
而其他一些尝试,诸如:
- Gazelle:国外著名 PT 架构,然而部署安装略麻烦,且纯英文界面。国内曾有人尝试翻译并建站,然而该主比我还不靠谱,以致于在 17 年度被人提及是开站狂魔 2333。此外就目前看 TVPlay 这个基于 Gazelle 的国内剧集站点现状比一滩死水还不如。
- YoRHa:根本没有人知道的国内构架,主要原因是因为基于 ThinkPHP 的构架并没有完成 23333,作者曾在 PT 吧发过主贴 【20171009】开源一个国产 PT 项目…【pt 吧】_百度贴吧 ,而且目前 demo 还存活(并开放 debug 模式),但已经有一段时间没有进行更新了 Orz。
- meanTorrent:同样是一个国内开源框架,基于 Node.js,同样部署安装麻烦(后面会具体讲~)。目前主站被人戏称(实际是官方简称)是地雷站 ,但就我目前感觉,迈的步子有些大——一方面,过于绚丽的前端对于 PT 是否需要值得思榷;另一方面,主站目前只接受 1080P 的一些规定是否在站点初期有利于发展。此外,该站积分策略、上传方式中的一些不同与 NP 的新形势新方法,对于已经在 NP 惯性中的使用者来说是不是能很快适应。这些都要经过时间的考验,毕竟今年 6 月(2018 年 6 月)也才正式上线。
- TBsource:基于 PHP,是 NP 的前身,应该也就只有 CFFBits 以及 TTG 这种_远古_站点在使用了吧~
- XBNBT: 一个基于 C++ 的构架,国内就只有紫荆 PT 在使用。
- 其他一些在 Discuz 基础上修改的 tracker:这块多为自己写的,而且未能找到公开 repo,在此仅作站点列举:六维空间、北交知行、天雪 PT。
所以,面对众多的 NP 改 站点来说,其实这个古老的(甚至连官网都挂了的)架构依然在支撑着国内 PT 网站的运行。
缺陷
但是从现代的角度来看 NP,我们其实能发现很多问题。
有些属于已经被发现漏洞,多为跨站请求类以及 SQL 注入类。截止目前(2018/7/19),在 国家信息安全漏洞库 中以 NexusPHP 为关键词搜索可以找出近 26 条记录 。

而更多被诟病的其实是其代码架构过于老旧也不宜于维护。下面列几点我印象比较深刻的:
- 使用这个 mysql 已经被抛弃的库(PHP 5.5.0 起废弃,PHP 7.0.0 起移除),而不是 mysqli 库或 PDO 库。而 PHP 7 至少从评测上看,执行效率比 PHP 5 优秀很多~
- 代码使用 print 等方式输出网页。项目受限于时代背景,没有使用 MVC 等先进思想。
- 数据库设置不合理,大量查询以及写入语句落在
users以及torrents等表上,造成数据表过热,故当站点人数过多或者种子数过多时,对站点所在服务器配置要求极其高(譬如 NPU 就因搜索问题换用外挂搜索引擎);而另一方面,诸如 faq、rules 这些应该可以直接静态输出的却使用数据库进行存储(估计是为了多语言支持) -
torrentsrss.php页面对 passkey 是否存在没有进行检查,导致非站内用户能通过构造相关链接直接读取站内 ** 所有 ** 种子信息。(部分站点已经修复这个漏洞)
目前分支情况
鉴于 NP 在很早之前就已经停止维护(Github 上停留在 7 年前,即 2011 年),目前很多使用 NP 作为基础架构的站点都对其进行了一定的改良。我仅从用户体验(比如前端页面的更改)将站点分成以下几类:
- ** 基本没怎么动 **: 不得不说,很多站点对原始 NP 模板并没有进行修改(这是句瞎话,比如 BYR 看起来和原版似乎一模一样,但是后端的修改还是挺多的;又如二娘,修改了种子的 BUFF 系统。)。但其实不管该站 Sysop 到底出力没出力,都可以将对应站点视为一个模板。
- ** 葡萄 **:该前端模板将个人信息做成置顶栏,而不是和基本模板一样放在导航栏之下。种子搜索增加“随意看看”。

- ** 蝴蝶 **:以蝴蝶和珞樱为代表,对搜索词的词长存在限制,拥有用户自定义 Javascript 以及自定义 css。
- ** 蚂蚁 **:虽然蚂蚁因为一些原因已经停止运营,但是模板并没有消失 2333。目前仍有很多新站使用蚂蚁的模板进行建站,如_高清街_以及_美盒子_(都是小站)。我个人不是很喜欢蚂蚁的模板,它将一个种子的所有信息使用两个 tr 加一堆 rowspan 进行合并展示,在我看来其实增加后期维护的困难程度,尤其是在没有模板引擎的 NP 构架之下。

截图为他人提供的美盒子截图。
- ** 蒲公英 **:蒲公英是魔改 NP 最为成功的一个站点。在它之前或者之后都有人尝试将 Bootstrap 与 NexusPHP 进行结合,虽不能说他们都失败了,但至少 NPU 成为了一个典型喵喵喵。。其他一些更改,比如 rp 系统、自动转种系统等都是该站点特点。
- HDA:良心站点 HDArea 添加了种子预告系统,后被集市使用。(毕竟这两个站点早期开发是同一个人)
嘛,我影响稍微深刻的就这些站点,以及他们使用的模板。其他还有一些站点,此处就不一一列举了。
而从公开仓库来看,目前站点公开并有在更新代码的有以下:
- lwenxu/jmbits:https://github.com/lwenxu/jmbits
- nwafu-mta/mtpt:https://github.com/nwafu-mta/mtpt
- zcqian/tjupt:https://github.com/zcqian/tjupt
- QingyingPT/QY-PT-tracker:https://github.com/QingyingPT/QY-PT-tracker , 非完整代码
也确实是寥寥无几~
为了去了解站点构架,一个简单的搭建过程也是需要了解的。
NP 搭建的最重要注意点是,** 使用的 PHP 版本最高不应该超过 5.6,并安装 memcache 软件及 PHP 扩展 **。对数据库版本要求不是很严格,我使用 MySQL 5.7 测试可行。
本人写的十分简略(因为真心没有什么好讲的),如果有必要,还请参照他人的详细搭建过程。
Linux 下搭建
LNMP 环境及 Memcache
网上的教程真心啰嗦,lnmp 一个一个的写过去,我个人还是喜欢用一键包来配置。lnmp1.5 的自动值守命令为
1 | screen -S lnmp |
复制粘贴,然后接杯奶茶等编译完成,我们基础的 lnmp 环境就搭建好了。(注意:这样安装后主 PHP 版本为 5.5,如果希望主版本用 7.x 的请自己使用 LNMP 一键安装包无人值守命令生成器 生成值守命令或者交互式安装,然后 ./install.sh mphp 添加多 PHP 支持)
然后安装 memcache,在 lnmp1.5 文件夹中进入 lnmp 解压后的目录,执行:
1 | ./addons.sh install memcached |
选择 php-memcache 即会安装软件及 PHP 扩展。
NP 源码及数据库
NP 源码个人建议从 SourceForge 中获取,而不是从 Github 仓库。(之前 Blog 也说过,Github 上的建表语句有问题)故,依次进行:
- 从 NexusPHP - Browse Files at SourceForge.net 下载最新的 zip 包并解压到对应网站根目录即可。
- 使用 phpmyadmin 或者其他 CLI 软件恢复
/_db/dbstructure.sql文件记录。 - 修改
config/allconfig.php文件的以下内容使其对应:
1 | ‘SITENAME’ => ‘站点名称’ |
- 设置目录权限 777,因为 NP 的站点配置是通过操作 config 目录下文件的修改完成的。
1 | sudo chmod 777 /dir/to/your/nexusphp |
- 自己访问网站然后注册一个用户名,接着进入数据库管理(phpMyAdmin),在 users 表里面找到你注册的用户,编辑它的 class 属性为 16
Windows 下搭建
Windows 下搭建我个人推荐使用 Laragon 作为基础环境,因为相比其他 WNMP、WAMP、XAMPP,环境管理更加方便,内置软件更为齐全。例如我选择的就包含了几乎全套我想要使用的工具 2333

然而需要注意的是,默认 Laragon 提供的是 PHP 7.x,我们需要额外到 PHP 官网上下载 PHP 5.5 版本的 Portable 以及 Memcache 扩展。下载位置分别如下:
- PHP 5.5:到 PHP 官网的历史发布页面存档 https://windows.php.net/downloads/releases/archives/ 中找到_php-5.5.38-Win32-VC11-x64.zip_ 下载并将解压到
laragon\bin\php目录 - php-memcache: http://pecl.php.net/package/memcache 中下载,并解压至
laragon\bin\php\php-5.5.38-Win32-VC11-x64\ext目录,之后你就可以在 Laragon 的切换 PHP 版本并启用该插件。
完成基础环境的搭建后,Win 下关于 NP 自身的文件以及数据库均与 Linux 下类似,在此不累述。
搭建中一些可能的问题
- ** 直接提示 HTTP ERROR 500** :多数情况下是使用了 PHP 7.x 或者其他高于 5.6 的版本,建议使用 PHP 5.3-5.5 之间的版本进行搭建。
- Warning: Memcache::connect() [memcache.connect]: Can’t connect to localhost: 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。 : 修改
classes\class_cache.php中的 localhost 为 127.0.0.1 - ** 点击登陆后提示
Error: Errno:0 SQL:;**: 使用 Github 上源码(这个源码真的是只能远观不能亵玩 233)搭建,换用 SourceForge 的源。 - 其他待补充~
meanTorrent
简介
在简单的介绍完 NP 的历史以及搭建,让我们先跳出 NP 框架,了解下其他的一些前面讲过的框架及其搭建过程。
meanTorrent 是目前来看,国人新框架中功能最为齐全、开发程度较高的一个。(其他我了解的都基本在开发过程中滴说)
从官方的介绍来看:
meanTorrent - MEAN.JS BitTorrent Private Tracker - Full-Stack JavaScript Using MongoDB, Express, AngularJS, and Node.js, A BitTorrent Private Tracker CMS with Multilingual, and IRC announce support, CloudFlare support.
相比已经停止开发维护的 NP 框架,一个有正经团队维护的项目从好的看,出现问题能统一修复解决,但从另一方面,有点剥离站点个性化的需求——从目前项目列出来的几个站点来看,站点雷同程度 ** 有过之而无不及 ** 。反正国人擅长建站,小站死了又是一批,能活成大站就是可以收割的时候 2333)
同样考虑到更新频繁这一点,本处的搭建手记也仅做示例,具体还是请参见项目主页 README 的介绍。
2018.08.27 请注意 meanTorrent 自
v1.8停止开源维护。且该版本存在_严重_的信息暴露漏洞,** 不建议使用该框架建站 **。
2019.07.24 MINE 站已经长时间 522,而本月的 18 号另外一个用 meanTorrent 建站的中型站点 PTDream + 也宣布重新回到 NPHP 框架,实际也意味着 meanTorrent 框架的失败了。
依赖分析
meanTorrent 其所用的依赖十分基础:Git(版本管理)、Node.js(运行程序)、MongoDB(数据库) 、Bower (浏览器包管理器)。

开机及环境准备
按照本人惯例,开一台 Vultr (←这里有个很生硬的 afflink) 的 $5 虚拟机进行搭建测试,系统为 Ubuntu 16.04,地点随意。
同样,对基础依赖不大,所以全部程序直接包管理安装即可,喜欢折腾的可以通过源代码编译安装,但这里只是测试(踩坑),所以一切就简。
1 | sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4 |
然后安装 npm 的包管理器 bower (话说现在不应该都用 Webpack 或者 Yarn 了嘛?)
1 | npm install -g bower |
安装 meanTorrent
** 建议使用非 root 账户进行安装!请使用 adduser 以及 visudo 创建新账户并赋予新账号超级用户权限。**
首先从 Github 上 clone 一份源代码来
1 | git clone https://github.com/taobataoma/meanTorrent.git |
然后使用 npm 安装依赖(过程中一堆 WARNING 都可以不用管 233)
1 | cd meanTorrent |
但似乎还是有问题,报错如下。在安装 node-gyp、iconv 以及 sharp 的时候报错。
1 | rhilip@vultr:~/meanTorrent$ npm install |
很明显的,还是出现了依赖缺失的情况,根据项目自身的介绍、 node-gyp 以及 lovell/sharp#1087 的相关提醒,安装 libicu-dev、GCC 编译库(主要是 c++ 以及 make 这两个会被 node-gyp 调用)以及 python-dev。然后重新安装依赖。
1 | sudo apt-get install libicu-dev build-essential python-dev python-pip |
使用 npm start 运行。过程中如果出现以下报错,说明 bower 以及相关浏览器端依赖没有正确安装(特别是在 root 账户下,这里直接使用新用户解决)。按照作者的建议是使用 bower install --allow-root && bower prune --allow-root 手动装一下。
1 | rhilip@vultr:~/meanTorrent$ npm start |
如果一切没有问题,那么在运行 npm start 后会提示一下信息:

Nginx 反代以及开机自启
通过以上环节,我们已经把所有的软件都基本配置齐全了,并启用了 meanTorrent 的开发环境。但是默认监听在 localhost 而不是 0.0.0.0 上,同样这个程序会因为 ssh 的断开而终止。所以我们需要安装 Nginx 以配置反代,同时使用 systemctl 或者其他守护工具(如作者使用多个 bashscript 脚本以及 forever 进行管理,如果你要使用 forever 的话,请先全局安装 npm i forever -g)使其能开机运行并崩溃重启。
安装 Nginx 也直接用包管理器吧,lnmp1.5 也提供单 Nginx 安装方式,反正怎么方便怎么来就 ok~
1 | sudo apt-get install -y nginx-extras |
然后将默认的信息全部替换为以下常见反代配置(无 SSL)
如果是在 CloudFlare 后,建议参照本人之前教程进行设置。(Cloudflare 下 Nginx 获取用户真实 IP 地址)
1 | server { |
然后重新载入 Nginx 配置信息并重启 npm,你就可以直接使用 ip 或者域名 来进行访问了。
1 | sudo systemctl reload nginx |

先不进行注册,退出我们来先写个 service 文件来使用 Systemd 进行守护管理。sudo vi /etc/systemd/system/meantorrent.service。并填入以下内容:
1 | [Unit] |
** 注意修改 User、Group、WorkinDirectory 为你自己的信息。**
然后使用以下命令重载 systemd 配置以及实现开机启动等管理
1 | sudo systemctl daemon-reload # 重载 systemd 配置 |
系统配置
个人建议这部分参考作者介绍 Getting Started With meanTorrent,对
config/env/torrent.js下文件进行配置修改。关于站点个性化设置,本处不再累述~
配置好邮件系统和 Tracker Announce 部分后,重启 meanTorrent,然后注册账号即可。如果你只是和我一样测试,不对邮件系统进行配置,默认情况下注册后因为无法发送邮件导致账号状态为 inactive 无法使用,需要进入 mongo 修改账户信息(其实我是默认 config 下进行账号注册的 2333)。方法如下:
1 | rhilip@vultr:~/meanTorrent$ mongo |
那么,就完事了~

框架结构及相关分析
在实质性的进入 Tracker 内部逻辑之前,让我先水一篇分析性的文章~
框架结构
- NexusPHP
像 NP 这种较老的框架并没有一个很明显的架构,各项信息杂糅在一起。但从导航栏相关中,大体可以分为以下几个子模块。
以下分类方式仅代表本人意见。

当然,目前各站在这个基础上均增加了一些新的系统,比如(万恶的)勋章系统、发布预告系统、转种系统(含自引用与他站引用)、任务系统、考核系统;对原有系统也有些许扩展,例如 Bangumi 榜单、AniDB 榜单等的添加。
- meanTorrent
meanTorrent 的可以在其 modules 下明确的了解其架构。撰稿时,架构如下:

Tracker 请求生命周期
从整个请求流程来看,用户的 Bittorrent 客户端使用 HTTP GET 的形式向 Tracker 服务器发起请求,Tracker 服务器根据内部逻辑向数据库及缓存请求请求相关信息,并最终回复给用户。具体流程可见下方简图:

当然上面的肯定过于简单了,没有对 Tracker 的内部逻辑进行分析,而就 Tracker 的内部逻辑来看,以 NP 这个面向流程的框架为例子,简图如下:

而从整个 Tracker 网络(见下方图片示意)来看,用户在请求后,Tracker 并不参与文件交换,同样,也不能真实的获取用户实际交换信息情况。(于是,我又可以就这个方向水一篇 SP 了)

Tracker 分析
在这一手记前,首先先列一下几个相关文件,以方便快速查阅:
- BEP 0003 :The BitTorrent Protocol Specification
- BEP 0007 :IPv6 Tracker Extension
- BEP 0023 :Tracker Returns Compact Peer Lists
- BEP 0048 :Tracker Protocol Extension: Scrape
- Private Tracker 实现
- ZJUT/NexusPHP/announce.php ,同时也包括其他开源的 NP 魔改架构,如 nwafu-mta/mtpt、zcqian/tjupt
- taobataoma/meanTorren/modules/announce/server/controllers/announces.server.controller.js
- WhatCD/Ocelot/worker.cpp (Gazelle 框架背后的主程序)
- mojie126/YoRHa/application/announce/controller/TrackerController.php
首先从最简单的信息查询来看,BT 客户端会在还未正式向 /announce 发送请求之前,会向 /scrape 先发送请求(一般在种子 添加或者校验的时候),请求头仅添加种子的 info_hash 信息,示例如下:
1 | GET http://nexusphp.localhost/scrape.php?passkey=110099109e337b7e335aa368200d7907c&info_hash=%e4%40%ad%c6%27%db%02%40%f7%c8%ed%9e%7b%aab%a3%e1gFW HTTP/1.1 |
关于 scrape 的相关定义及返回信息在之前列出来的 BEP 0048 中,根据定义,这次 抓取(scrape) 会向用户返回一个字典描述对应种子的完成、未完成以及下载中的情况。本处直接引述定义:
The response to a successful request is a bencoded dictionary containing one key-value pair: the key
fileswith the value being a dictionary of the 20-byte string representation of an infohash paired with a dictionary of swarm metadata.
根据 NP 的实现(见 NexusPHP/scrape.php ),会从 param 字段中搜索并匹配出来 info_hash 信息,如果 param 中没有能匹配出 info_hash,则会直接返回站内 ** 所有 ** 种子的做种信息。(如下图)

以上问题修复 patch 见 :lock: Not allow empty info_hash when request scrape page by Rhilip · Pull Request #11 · zcqian/tjupt,截止目前,多数站点未对该问题进行修复。
而如果存在 info_hash 的话,则会对每一个提供的 hash 值进行数据库查找,如果查询结果不存在,则返回 Torrent not registered with this tracker. 的错误,而如果存在,则以一个 benc 编码的字典返回结果。其 json 格式如下:
1 | { |
此外,一个正常的客户端(例如 Transmission 2.94)会定期向 Tracker 发送(announce)以下信息,并期望从 tracker 中获取回复以获取其他 peer 信息(这里仅指 Private Tracker,其他的还有 DHT 网络、用户交换等方式)。
1 | GET http://nexusphp.localhost/announce.php?passkey=db534098baaaa68bd725aaaae3051518&info_hash=aaaaaaaaaaaaaaaaaaaa&peer_id=-TR2940-lhqkh1jtwjqp&port=21736&uploaded=0&downloaded=0&left=739573325&corrupt=0&key=DDDD2A2B&event=started&numwant=200&compact=1&no_peer_id=1 HTTP/1.1 |
而 tracker 则会根据 GET 字段中的 compact 以及 no_peer_id 两个字段分别返回不同构造的结果,并设置相应头为
1 | HTTP/1.1 200 OK |
当 compact=0&no_peer_id=0 时,其返回的 json 格式如下:
1 | { |
其中, peer_id 视用户 Requests 字段这一项可以不要,而如果用户申请使用 compact 的形式返回,那么 peer 字段则会返回一个 string 而不是 dict。
如果发生错误,则会返回一个错误字段(string),JSON 格式内容如下:
1 | { |
Bencode 编码
在上面的例子中,我都是以 json 格式的形式来展示 tracker 返回的 Response 信息,但实际上,返回的信息是以 Bencode 的形式进行编码的。关于 Bencode 的介绍,可以访问Bencode - Wikipedia。这里我们只需要知道一下编码规则就行:
| data types | raw | encoded |
|---|---|---|
| int | -42 | i-42e |
| string | ‘spam’ | 4:spam |
| list | [‘XYZ’, 4321] | l3:XYZi4321ee |
| dict | {‘XYZ’: 4321} | d3:XYZi4321ee |
这些甚至不需要你自己一个一个拼合,现在有超多的库帮你进行拼合,你只需要构造好相应的字典,直接调用即可,例如:
- PHP:sandfoxme/bencode、rchouinard/bencode、dsmithhayes/bencode、bhutanio/torrent-bencode
- Python:amyth/bencode、utdemir/bencoder、jcul/bencode、fuzeman/bencode.py
- Node.js: themasch/node-bencode、benjreinhart/bencode-js
构造一个 Private-Tracker 的 Demo
在这节及之后的 PT 架构书写过程中,我将使用 ThinkPHP 5 作为 MVC 框架,rchouinard/bencode 作为 Bencode 编码库,实现一个演示性质的 Private Tracker。在此,我将默认你已经对前面的内容有所理解,并对 PHP 以及 composer 有了解运用。
该项目代码见: https://github.com/Rhilip/Simple-Private-Tracker ,仅供学习无法运行~
请注意,本文所列方法,仅表示本人的一种实现。实际只要符合 BEP 0003 以及 BEP 0027 的都是可行的实现~
请注意,本处所列代码并不一定是最新的,仅代表思考逻辑过程,具体代码请看 repo
相关 commit:c2c37e668a3f63722b6d4d736e957c8cda76b2a8
基础准备
首先,我们需要准备好 PHP 环境(建议为 7.x)以及数据库,因为学习,所以缓存暂时使用文件缓存。并使用 composer 安装 ThinkPHP5 以及 bencode ,其命令分别如下:
1 | composer create-project topthink/think=5.0.* tp5 --prefer-dist |
准备相关数据表,分别用来存储 Torrent(种子信息)、User(用户信息)、Peer(做种人信息)、Snatch(做种完成情况),此处为了方便(偷懒)直接使用 NP 的建表语句(-> 见 NexusPHP/_db/dbstructure.sql 相关)就行(实际很多字段不需要)。顺带也方面后续兼容~
而文件夹方面,依次添加以下文件:
1 | ├─application |
并在路由(route\route.php)中注册两个控制器
1 | Route::get('tracker/scrape','tracker/Index/scrape'); |
并在设置中开启你的 debug 模式以及应用 trace,准备 postman 或其他作为调试工具。
方法准备
我们先要为 TrackerController 准备一些公用方法,分别用于构造响应信息(包括正常的以及错误)、禁用浏览器访问。修改 app\Http\Controllers\TrackerController.php 为以下信息:
1 | <?php |
我们将在 $errormsg 中定义错误信息,并在 announce 以及 scrape 这两个公开方法中定义具体逻辑。** 而所有的响应应该使用 bencResp 构造。**
构建 Scrape
相比较为复杂的 Announce 逻辑,我们先来处理较为简单的 Scrape 逻辑:
- 从请求头中获取所有
info_hash信息, - 从数据库中匹配出来对应的做种内容,
- 构造返回或错误信息。
下面我们开始写 Scrape 的具体逻辑。首先我们先禁用掉 非 GET 请求 以及 浏览器及非 BT 客户端请求。代码如下,但实际上,因为已经设置的路由关系,我们其实已经禁止了非 GET 请求,这里需要不需要都无所谓了
1 | // 1. Block NON-GET requests, (though it should be block in Router) |
然后我们从请求头中获取 info_hash 信息,并检查其是否存在(这里附加对各个 info_hash 的字节数进行检查也行)。当其不存在时,返回错误信息。
** 注意 **,根据 BEP0048 规定 ,info_hash 在 url 中是以 info_hash=xxxxx&info_hash=yyyyy 的形式存在的,故本人之前的写法是错误的(之前写法见Archive.org 的备份,只能匹配 info_hash[]=xxxx 的情况)
应为:
1 | preg_match_all('/info_hash=([^&]*)/i', urldecode(Request::server('query_string')), $info_hash_match); |
针对 info_hash 未找到的情况进行处理。
1 | if (count($info_hash) < 1) { |
使用查询构造器生成 SQL 语句并查询,并对查询结果进行检查;当数据库中未检查到该种子时,返回错误信息。
1 | $res = Db::table("torrents") |
如果没有任何问题,我们需要把原来数据库中查询的结果(如下)进行转换
1 | array(1) { |
方法如下,并最后使用 bencResp($obj) 的方式进行编码并发送
1 | $rep = [ |

PT 站的做种和魔力值是如何增加换算的?
PT 站的做种和魔力值是如何增加换算的?
相信混了一段 PT 界的小伙伴,一定头疼一个问题,各大站点的 PT 魔力值是怎么计算的呢?
以下是整理的帮助理解 PT 网站的魔力值计算方法。
** 统计工具采用 PTTools 这款 PT 助手 的截图(隐私部分已做打码处理)**

首先要说一下的是,国内 PT 站点基本上都是同一套魔力值公式,在计算魔力值的差异上基本不大。但是相信很多小伙伴还是云里雾里。下面上一张魔力值计算的公示图 (国内 90% 的 PT 网站都采用的这套公式)

如图所示,很复杂的一套公式。文科生包括小编我在内,对这个公式真实“恨之入骨”~ 当然了,其实也不复杂。经过小编通过多种资料的查询,最终得出的结论如下(简易版):
**1. 发布时间较长 **
**2. 做种人数小于 10 个 **
**3. 体积越大越好 **
只要在保种的同时满足以上 3 点,基本上跑满进度条是很有可能的!当然啦,如果小伙伴需要了解更加详细的资料,可以继续往下看。
** 魔力值分析 **
魔力值的 A 公式如下:


式中
- A 为中间变量
- Ti 为第 i 个种子的生存时间, 即自种子发布起到现在所经过的时间, 单位是周
- T0 为参数。T0 = 4
- Si 为第 i 个种子的大小,单位是 GB
- Ni 为第 i 个种子当前的做种者数
- N0 为参数。N0 = 7
- B 为 1 小时中用户获得的做种魔力值点数
- B0 为参数,代表用户 1 小时获得魔力值的上限。B0 = 50
- L 为参数。L = 300
**A 值 **
我们只讨论单个种子的情况,因此忽略掉加和运算,该公式包含三个变量,为了研究每个变量的影响,我们把公式拆分
(1)1-10^(-0.25*i) 种子存活周期影响
(2)1+1.414*10^(-0.167*(i-1)) 当前做种人数影响
其中 i 为变量,分别代表周期数(以周为单位)和种子数
(1)函数图形如下

从图中我们可以很明显看到:8 周后时间对函数值没有明显影响。
(2)函数图形如下

从图中我们可以很明显看到:大于 10 个做种人数后时间对函数值没有明显影响。
(3)(1)*(2)的函数图形为
我们假设做种数和周期的数值相等,可得如下图像

从中可以看到,种子数计时间为 5 时 ,有最大值。
(4)(1)*(2)*Si 的图形
我们让做种数、大小和周期的数值相等,可得如下图像

**B 值 **
B 值(也即每小时魔力值)与 A 值关系见下图:

在 0-300 时基本是直线关系。
** 特殊情况分析 **
当周期大于 8,种子数多于 10,函数(1)(2)的值不再随他们的增加而明显改变,因此以此时的值代替周期大于 8,种子数多于 10 的值是合理的。
下面分析满足以上情况时的魔力值。
首先周期等于 8,种子数等于 10 时,函数(1)(2)的值分别为 0.99 和 1.04,则 A 值为 A=1.0296*Si ,B 值为 B= 31.85*atan((1.0296*Si)/300)
其图形如下

重要结论:经拟合,以上线性方程为 y=0.09658x+0.545,x 为种子尺寸,y 为一个种子每小时魔力值。相关系数为 0.99867,标准偏差为 0.2886。该方程适合周期大于 8 ,做种数多于 10 的情况。
同时我们还可以得到一个重要结论:占用同样的做种磁盘空间,多个种子和一个种子所获得的魔力值是相等的(不考虑 0.6*12,适用于周期大于 8,做种数多于 10 的情况),因为他们的 A 值是相等的,比如 100g 种子 1 个和 1g 种子 100 个,他们的 A 值可用 A=1.0296*Si 计算,显然二者相等。
** 结论 **
1. 8 周后时间的增加不会让魔力值明显增加;
2. 做种人数超过 10 后,做种人数的增加不会明显减小魔力值;
3. 一个种子存活 8 周后,且做种人数超过 10,种子尺寸小于 200G 时,魔力值与种子大小有近似直线关系,即 B=0.09658x+0.545;
4. 占用同样的做种磁盘空间,多个种子和一个种子所获得的魔力值是相等的。
以上就是 PT 站点魔力值的计算方法,看似复杂,其实主要记住最重要的三点“** 大 ” “ 老 ” “ 少 **” (即种子体积大,种子存活时间长,种子的做种人数少!)
to be continued…