tinyTorrent: 从头写一个 Deno 的 BitTorrent 下载器

BitTorrent 想必大家应该都不陌生,中文名叫做“种子”。

“种子”到底是什么?我一直不太清楚。在写这个项目之前,我对“种子”的认识停留在使用层面。

当我想找一个资源的时候,我会搜索 xxx 种子,一般会在一些非常不知名的小网站里面获取到以 .torrent 结尾的种子文件,然后使用迅雷或者 uTorrent 这样的下载器来下载。

如果迅雷有一点速度,哪怕几 kb,那么大概率我充个会员就搞定了。这个软件就是这么的恶心,不用有时候又没办法,像极了人生。

其他下载器比如 uTorrent 的话就一切随缘了,有些资源非常快,有些资源非常慢,有些一开始慢后来快。

这些问题是怎么回事?有没有改进的办法?在读 Jesse Li 的 Building a BitTorrent client from the ground up in Go 之前,我从没想过。

BitTorrent(BT)

Jesse Li 的博客图文并茂,讲述了如何用 Go 开发一个 BT 的下载器。内容涉及到 BT 协议以及下载器的代码设计,思路清晰,值得一读。

对于喜欢动手的朋友,可以先关掉这篇博客,参考 Jesse 的代码尝试自己写一个 BT 下载器。写完以后再回来,对比我用 Deno 开发的下载器,相信会有不一样的收获。

我们先来看一下 BT 是什么。

Tip
BT 一直在演进,新的功能有 DHT,磁力链接等,这里我们关注早期版本的 BT。

BT 是一个协议,和 HTTP, FTP 一样,是一个应用层的协议,这个协议被设计用来实现 P2P(Peer to Peer) 下载。

P2P 我想大家都很了解,中文翻译为点对点,不仅可以用来下载,还可以用来金融😉。

传统的下载是客户端请求服务器获取资源,下载方和资源提供方的角色很清楚。这样做的优点是简单,易于理解,我要下载东西,我就去请求服务器,缺点也很明显:

  • 一旦服务器故障,大家都无法下载
  • 服务器带宽有限,下载的人多速度必然下降

而 P2P 则不一样,每一个客户端同时也是服务器,从别人那里下载资源的同时,也提供资源给到别人。这样一来,就规避了服务器模型的缺点:

  • 每个人都是服务器,除非所有机器都故障了,否则网络依旧可以运转
  • 不会去请求单一机器,带宽得到最大利用

The BitTorrent Protocol Specification 是 BT 协议的官方文档,里面阐述了 BT 的核心概念和设计,但是漏了很多细节。推荐配合 Unofficial BitTorrent Specification 这个民间整理的版本一起看,会更有助于理解。

当学习一个新知识的时候,我喜欢用「提问法」来帮助自己梳理,带着问题去找资料会更有方向。

现在我们知道 BT 是基于种子文件的一种 P2P 下载协议,那么很自然地我们可以提出如下的问题:

  • 种子文件是什么格式?里面存储了哪些信息?
  • 下载器如何寻找 Peer?如何让别的 Peer 找到自己?
  • 下载时是以整个文件为单位吗?还是会分块,如果分,怎么分?
  • 怎样从 Peer 那里下载文件?怎样提供文件给到 Peer 下载?
  • 使用种子下载一个文件的完整流程是怎样的?

Torrent File

我们先来看第一个问题,种子文件的格式和里面存储的信息。

种子文件使用了一种名为 Bencode 的编码,这个编码非常简单,只支持如下四种数据类型。因为存在 List 和 Dictionary,所以也有能力表达复杂的数据结构。

  • Byte String
  • Integer
  • List
  • Dictionary

deno-bencode 是我给 Deno 写的一个 Bencode 编解码库,我们现在使用这个库来看看种子文件中到底有什么。

我们用 Debian 的官方种子文件来测试。

// decode.ts
import {
    decode } from "https://deno.land/x/bencode@v0.1.2/mod.ts"

const file = Deno.args[0]
console.log(decode(Deno.readFileSync(file)))
$ wget https://cdimage.debian.org/debian-cd/current/amd64/bt-cd/debian-10.6.0-amd64-netinst.iso.torrent
$ deno run --allow-read decode.ts debian-10.6.0-amd64-netinst.iso.torrent
{
   
  announce: "http://bttracker.debian.org:6969/announce",
  comment: '"Debian CD from cdimage.debian.org"',
  "creation date": 1601120878,
  httpseeds: [
    "https://cdimage.debian.org/cdimage/release/10.6.0//srv/cdbuilder.debian.org/dst/deb-cd/weekly-builds...",
    "https://cdimage.debian.org/cdimage/archive/10.6.0//srv/cdbuilder.debian.org/dst/deb-cd/weekly-builds..."
  ],
  info: {
   
    length: 365953024,
    name: "debian-10.6.0-amd64-netinst.iso",
    "piece length": 262144,
    pieces: Uint8Array(27920) [
      144,  55, 173,  67, 115, 234, 169, 248, 222,  41, 139, 142, 125,
      100, 183, 130,  43, 148, 137, 130,   2, 194,  83, 109, 140, 147,
      123, 174, 234, 135,  58, 207, 217, 141, 107,  86, 245, 137,  79,
      150,  23,  33, 151, 157, 125, 159,  97,  10, 200, 137,  36, 158,
       74,  19,  97, 194, 171, 164,  32, 145, 175, 213,  91, 193, 120,
       26,  89, 109, 114,  61,  90, 166, 168, 137, 218, 154, 219, 119,
      107,  46, 240,  50, 134, 161, 162,  18, 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值