admin 管理员组文章数量: 1184232
从一个链接引发的思考
magnet:?xt=urn:btih:46be2d71cd2d690fdce026299eca164dbdaefe01
这就是磁力链接,那什么是磁力,为什么一个字符串就能下载资源?
一、magnet 链接
完整的 magnet 链接包含以下参数:
magnet:协议名。xt:exact topic的缩写,表示资源定位点。btih(BitTorrent Info Hash)表示哈希方法名,这里还可以使用 SHA1 和 MD5。这个值是文件的标识符,是不可缺少的。btih:这是整个torrent文件内容的一个唯一标识符,通常是通过SHA-1哈希算法生成的,用于识别特定的种子或资源,它是 40 个 16 进制字符串,同时也是种子文件的 info_hash,是每个种子的唯一标识码。dn:display name 的缩写,表示向用户显示的文件名。tr:tracker 的缩写,表示 tracker 服务器的地址,这些服务器帮助客户端找到其他拥有该资源的对等节点。kt:关键字,更笼统的搜索,指定搜索关键字而不是特定文件。mt:文件列表,链接到一个包含磁力链接的元文件 (MAGMA - MAGnet MAnifest)。
实际上,在上面的示例中只需要一个btih参数即可,它是有一个发展过程,可以去阅读阮一峰的 BT 下载的未来。
当互联网上每一台机器都在自动交换信息的时候,谎言和封锁又能持续多久呢?
请回忆一下,你是如何使用BT下载的。
首先,你从浏览器中找到你感兴趣的内容,下载相应的torrent文件。然后,你用一个BT下载客户端软件,打开这个文件。这时,客户端软件就会根据torrent文件中的网址,自动连接Tracker服务器,从它那里接收到其他正在下载该文件的人的网址名单。下一步,软件就一一与名单上的网址取得联系,从他们那里获取文件的片段,直到整个下载完成。
从这个过程中,我们可以看到,Tracker服务器是整个BT下载的灵魂,文件可以不存在,但是Tracker服务器却不能不存在。要是连不上它,BT下载根本没法启动,因为你无从知道,找谁索要文件。就是由于这个原因,Tracker服务器成为了版权组织打击的重点。他们的想法很明确,只要除掉了Tracker,BT下载就完了。他们的理由是,虽然Tracker本身不传递内容,但是为传播盗版提供了便利,是犯罪的协助者。更何况,Tracker服务器的网址是公开的,很容易找到它的所有者,逃都逃不掉。
在这种形势下,Tracker提供者的日子都很难过。海盗湾是世界排名第一的Tracker提供者,它已经在被追杀了。排名第二的Demonoid从今年9月15日起,就一直处于维护状态,不知道何时重新开放。其他的Tracker提供者基本上也是在法律诉讼的阴影下度日。那些不提供Tracker服务,只提供torrent文件索引服务的网站,比如Mininova、Torrentz、isoHunt,日子稍微好过一点。但是明摆着,版权组织收拾完Tracker以后,就要收拾它们了。比如,今年8月,Mininova就在一场官司中败诉,荷兰法官判决,该网站必须移除所有侵权内容的torrent文件。
既然,Tracker服务器在法律上很难立足,那么有没有办法,在不使用Tracker的情况下,依然使用BT下载呢?
2002年,纽约大学的两个教授Petar Maymounkov和David Mazières发表了一篇论文,提出了一种真正去中心化的"点对点"下载模型,他们把它叫做Kademlia方法。Emule率先在软件中支持这种方法,KAD网络就是这样来的。到了2005年,BT软件也开始跟进了。目前,所有主流的BT下载客户端软件都支持这种方法。在BT下载中,这被叫做DHT协议(Distributed hash table,分布式哈希表)。
二、BT种子文件
使用 magnet 地址,我们就能下载到一个.torrent文件,这就是种子文件,当然你可以不下载种子文件而直接下载具体的资源文件。种子文件的内容遵循 BitTorrent 协议,内容经过 bencode 编码,它包含了如下内容。
多文件Torrent的结构的树形图为:
Multi-file Torrent
├─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
单文件Torrent的结构的树形图为:单文件Torrent没有files字段。
Single-File Torrent
├─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
使用过迅雷下载 magnet 的同学应该都很熟悉了,它会先弹出一个文件列表,你可以选择性的下载哪些文件,这是因为它先下载并解析了了 torrent 文件。
关于 BEP 规范
它是 bitTorrent 协议的文档,由于此协议一直在发展更新,所以它使用版本号的方式来表示,即BEP x,BEP 后面的数字代表文档编号,后面的编号文档就是对前面文档的修正与补充,往往会增加新的特性。
1 号文档地址为 https://www.bittorrent/beps/bep_0001.html,12 号地址为 https://www.bittorrent/beps/bep_0012.html,依次类推。
三、DHT 网络(分布式哈希表)
先用我的理解描述一下:DHT网络是由散落在互联网上无数个节点组成的一个可以相互访问的网络空间,你先得认识其中某个人才能通过它加入进去,然后你在这个网络中认识了更多的人,互相加好了微信,然后,你需要下载某个资源(比如 46be2d71cd2d690fdce026299eca164dbdaefe01)的时候,你先去问这些熟人那里有没有,如果它们那里没有,它会帮你问它的熟人那里有没有,直到找到为止。
同时,你还可以主动的将自己电脑上的资源发布出去,比如将某个文件夹计算得到一个哈希值,然后发布到HDT网络上,称为做种,这样,只要你的机器开着,别人就可以使用这个哈希值来你这里下载。
DHT允许你从多个节点同时下载文件的不同部分,从而提高了下载速度并分散了带宽负载,所有传输的数据都经过哈希校验以确保其完整性。一旦所有的数据块都被成功下载,它们会被按照正确的顺序重新组合成原始文件。
每的节点需要保留自己附近的一部分节点信息,这就保证了整个网络没有单个的中心,即使一个节点下线了,依然可以通过其他节点来获取文件。
如果你谁都不认识怎么办?DHT网络的维护者会自己维护几个节点并对外公布,这就是大家的引导节点,后面会提到。
很显然,有了DHT网络之后就不需要Tracker服务器了,那么问题来了,为什么这些公开的DHT节点没有被版权维护者告上法庭呢,因为这几个服务器上不存储任何资源,它只是建群的群主,至于群成员之间在分享什么,它管不着。
如果按照上面遍历查找的话,那得查到后年马月,因此DHT网络设计了一套算法来组织这些节点和资源,以加速节点管理和查找。
Chord算法:它通过将节点放置在一个环形结构中,并利用一致性哈希算法来确定节点的位置和数据的路由。
Kademlia算法:它通过基于异或运算的度量来构建节点之间的距离概念,以实现高效的路由和数据存储。
CAN算法:它将节点放置在一个二维网格中,并通过分割和合并网格来管理节点和数据。
DHT算法讲解:分布式哈希表(DHT)与P2P技术
一个DHT节点包括:
- peer: 一个 TCP 端口上监听的客户端/服务器,它实现了 BitTorrent 协议。
- 节点: 一个 UDP 端口上监听的客户端/服务器,它实现了 DHT(分布式哈希表) 协议。
在DHT网络中查找某一个HASH值对应的资源,其过程是什么
在DHT(分布式哈希表)网络中查找一个特定HASH值对应的资源,通常指的是找到拥有该HASH值所代表的文件或数据块的peer节点。这个过程依赖于DHT协议和路由算法来实现高效的数据定位。以下是基于Kademlia算法的典型查找流程:
初始化
当一个新的节点加入DHT网络时,它首先需要找到一个或多个已存在的节点作为起点。这些节点可以是预先配置好的引导节点,如router.utorrent、router.bittorrent 和 dht.transmissionbt,它们都在端口6881上提供服务
查找过程
计算目标HASH值的位置:每一个节点和资源都被映射到一个环形空间中的某个位置。这是通过一致性哈希算法将节点ID和资源HASH值转换为一个固定大小的数值来完成的。例如,如果使用SHA-1算法,那么HASH值将是160位长的二进制字符串
发送查找请求:新节点向其已知的一个或多个节点发送find_node或get_peers请求,其中包含了目标HASH值。这一步骤类似于询问:“谁靠近这个HASH值?”
路由选择:收到请求的节点会检查自己的路由表(也称为手指表),寻找最接近目标HASH值的节点,并将这些节点的信息返回给发起请求的节点。如果查询的是get_peers,并且该节点有与目标HASH相关的peer信息,则直接返回peer列表;如果没有,则返回最近的K个节点
迭代查询:发起请求的节点收到回复后,会从返回的节点列表中选择最接近目标HASH值的节点,并再次发送find_node或get_peers请求。此过程重复进行,直到找到存储目标HASH值的节点或得到足够的peer节点为止。
结束条件:查找结束有两种情况:一是找到了负责存储目标HASH值的节点;二是已经遍历了所有可能更近的节点但仍未找到。在这种情况下,可能会得到一组peer节点,这些节点当前正在共享与目标HASH值相关的资源
结果处理
一旦找到相应的节点或peer列表,就可以开始下载资源了。如果是磁力链接(Magnet URI),则可以直接用这个HASH值构造出磁力链接,并将其用于BitTorrent客户端下载对应的种子文件和资源
四、Golang实现 BitTorrent 客户端
开源项目 github/anacrolix/torrent
文档 https://opendeep.wiki/anacrolix/torrent/loading-and-managing-torrents
1、命令行
此项目提供了命令行程序,可以先测试一下
go install github/anacrolix/torrent/cmd/...@latest
> torrent --help
options:
--debug, --no-debug: [true|1|false|0]
commands:
metainfo
announce
scrape fetch swarm metrics for info-hashes from tracker
download
bencode reads bencoding from stdin into Go native types and spews the result
version prints various protocol default version strings
serve creates and seeds a torrent from a filepath
create Creates a torrent metainfo for the file system rooted at ROOT, and outputs it to stdout
help help with subcommands
首先是 download 功能
> torrent help download
options:
--save-metainfos, --no-save-metainfos: [true|1|false|0]
--mmap, --no-mmap: [true|1|false|0]
--seed, --no-seed: [true|1|false|0]
--addr: (string)
--max-unverified-bytes: (tagflag.Bytes)
--upload-rate: (tagflag.Bytes)
--download-rate: (tagflag.Bytes)
--packed-blocklist: (string)
--public-ip: (net.IP)
--progress, --no-progress: [true|1|false|0]
--piece-states, --no-piece-states: [true|1|false|0]
--quiet, --no-quiet: [true|1|false|0]
--stats, --no-stats: [true|1|false|0]
--dht, --no-dht: [true|1|false|0]
--port-forward, --no-port-forward: [true|1|false|0]
--tcp-peers, --no-tcp-peers: [true|1|false|0]
--utp-peers, --no-utp-peers: [true|1|false|0]
--webtorrent, --no-webtorrent: [true|1|false|0]
--disable-webseeds, --no-disable-webseeds: [true|1|false|0]
--require-fast-extension, --no-require-fast-extension: [true|1|false|0]
--ipv4, --no-ipv4: [true|1|false|0]
--ipv6, --no-ipv6: [true|1|false|0]
--pex, --no-pex: [true|1|false|0]
--linear-discard, --no-linear-discard: [true|1|false|0]
--test-peer: (string...)
--file: (string...)
arguments:
<DownloadCmd.Torrent>: (string...) torrent file path or magnet uri
下载资源全部文件
torrent download magnet:?xt=urn:btih:46be2d71cd2d690fdce026299eca164dbdaefe01
下载资源的同时保存.torrent 文件
torrent download --save-metainfos=1 magnet:?xt=urn:btih:46be2d71cd2d690fdce026299eca164dbdaefe01
File 表示选择要下载的文件名列表,因为torrent里面可能包含多个文件,你可以选择下载哪些,要带上相对路径
其次是 metainfo 命令
magnet:根据 torrent 文件,生成 magnet 链接
pprint:打印 torrent 信息。
> torrent metainfo abcdefg.torrent magnet
magnet:?xt=urn:btih:46be2d71cd2d690fdce026299eca164dbdaefe01&dn=SONE-201
> torrent metainfo abcdefg.torrent pprint
{
"Announce": "",
"AnnounceList": null,
"InfoHash": "46be2d71cd2d690fdce026299eca164dbdaefe01",
"Name": "SONE-201",
"Name.Utf8": "SONE-201",
"NumFiles": 19,
"NumPieces": 2515,
"PieceLength": 524288,
"TotalLength": 1318305205,
"UrlList": []
}
2、使用示例
包括
- 根据 magnet 下载 torrent 文件.
- 解析 torrent 文件,得到 metainfo。
- 下载资源。
package bit_download
import (
"fmt"
"io"
"log"
"os"
"strings"
"github/anacrolix/torrent"
"github/anacrolix/torrent/bencode"
)
/*
解析 torrent 文件
github/jackpal/bencode-go
github/anacrolix/torrent/bencode
*/
func TestParseTorrentFile() {
parseTorrentFile("46be2d71cd2d690fdce026299eca164dbdaefe01.torrent")
// parseTorrentFile("demos/bit_download/downloaded.torrent")
// parseTorrentFile("demos/bit_download/46be2d71cd2d690fdce026299eca164dbdaefe01.torrent")
}
type TorrentFile struct {
Announce string `bencode:"announce"`
AnnounceList [][]string `bencode:"announce-list"`
UrlList []string `bencode:"url-list"`
Nodes []string `bencode:"nodes,omitempty,ignore_unmarshal_type_error"`
Info TorrentInfo `bencode:"info"`
}
type TorrentInfo struct {
Name string `bencode:"name"`
PieceLength int `bencode:"piece length"`
Pieces string `bencode:"pieces"`
Length int `bencode:"length,omitempty"`
Files []TorrentFileEntry `bencode:"files,omitempty"`
Publisher string `bencode:"publisher,omitempty"`
PublisherUrl string `bencode:"publisher-url,omitempty"`
}
type TorrentFileEntry struct {
Length int `bencode:"length"`
Path []string `bencode:"path"`
}
// 解析 torrent 文件,得到文件列表
func parseTorrentFile(filePath string) {
f, err := os.Open(filePath)
if err != nil {
log.Fatalf("Failed to open torrent file: %v", err)
}
defer f.Close()
content, _ := io.ReadAll(f)
var torrent TorrentFile
err = bencode.Unmarshal(content, &torrent)
if err != nil {
log.Fatalf("Failed to decode torrent file: %v", err)
}
fmt.Printf("Torrent Name: %s\n", torrent.Info.Name)
fmt.Println(torrent.Nodes)
fmt.Println(torrent.Info.Publisher)
fmt.Println(torrent.Info.PublisherUrl)
if len(torrent.Info.Files) > 0 {
for _, file := range torrent.Info.Files {
fmt.Printf("File with path '%s' and length %d bytes.\n",
strings.Join(file.Path, "/"),
file.Length)
}
} else if torrent.Info.Length > 0 {
fmt.Printf("Single file with length %d bytes.\n", torrent.Info.Length)
} else {
fmt.Println("No files found in the torrent.")
}
}
// 根据 magnet 下载 torrent 文件
func downloadTorrent() {
file, _ := os.OpenFile("demos/bit_download/46be2d71cd2d690fdce026299eca164dbdaefe01.torrent", os.O_CREATE|os.O_RDWR, 0644)
defer file.Close()
c, _ := torrent.NewClient(nil)
defer c.Close()
t, _ := c.AddMagnet("magnet:?xt=urn:btih:46be2d71cd2d690fdce026299eca164dbdaefe01")
<-t.GotInfo()
mi := t.Metainfo()
mi.Write(file)
fmt.Println("成功获取 .torrent 元数据!")
}
// 下载文件
func downloadTorrentByMagnet() {
dirname := "demos/bit_download/data2"
torrentFile, _ := os.OpenFile(dirname + "/46be2d71cd2d690fdce026299eca164dbdaefe01.torrent", os.O_CREATE|os.O_RDWR, 0644)
defer torrentFile.Close()
cfg := torrent.NewDefaultClientConfig()
cfg.DataDir = dirname
c, _ := torrent.NewClient(cfg)
defer c.Close()
t, _ := c.AddMagnet("magnet:?xt=urn:btih:46be2d71cd2d690fdce026299eca164dbdaefe01")
<-t.GotInfo()
log.Println("成功获取 torrent 元数据!")
// 保存 torrent 文件
mi := t.Metainfo()
mi.Write(torrentFile)
downloadAll := false
if downloadAll {
// 下载全部文件
t.DownloadAll()
} else {
// 指定文件下载
fileList := []string{
"SONE-201a.jpg",
"文宣/xp1024 -1024核工厂.url",
}
for _, f := range t.Files() {
for _, fileArg := range fileList {
if f.DisplayPath() == fileArg {
f.Download()
}
}
}
}
}
经过测试,发现DHT网络并不稳定,且下载速度很慢,这个很好理解,中国的网络环境要比发达国家的差很多,因为我们起步晚,我们国家拥有的IPv4地址很有限,所以我们广泛使用NAT,而NAT将严重影响P2P的效率。
为什么用迅雷下载magnet资源要比我自己下快那么多?
使用迅雷下载Magnet资源通常比普通下载更快,这主要归功于迅雷采用的一系列技术和优化措施。以下是几个关键因素:
多资源超线程技术:迅雷采用了基于网格原理的多资源超线程技术,能够整合网络上的服务器和计算机资源,形成一个高效的迅雷网络。在这个网络中,数据文件可以以最快的速度进行传递,大大提高了下载效率
P2P与P2SP混合下载:迅雷不仅支持传统的P2P(Peer-to-Peer)下载模式,还结合了P2SP(Peer-to-Server/Peer)技术。这意味着在下载过程中,迅雷不仅可以从其他用户那里获取数据,还可以从迅雷的服务器或缓存中获得加速
智能分流与负载均衡:迅雷具备智能分流功能,可以根据用户的网络环境动态调整下载策略,以最优化的方式利用网络资源。这种能力使得迅雷可以在不降低用户体验的前提下,对服务器资源进行均衡分配,有效减少网络拥堵和延迟
丰富的节点资源:由于迅雷拥有庞大的用户基础,其DHT网络中的节点数量庞大且活跃度高。当您尝试通过磁力链接下载资源时,迅雷可以通过其广泛的节点网络快速定位并连接到多个提供该资源的peer节点
高速通道与CDN加速:对于付费会员,迅雷提供了高速通道服务,这是一种基于内容分发网络(CDN)的技术,可以让用户充分利用物理带宽上限进行加速
离线下载与云端处理:迅雷会员还可以享受离线下载服务,即将下载任务提交给迅雷服务器完成,之后再由用户从服务器上下载已完成的任务。这种方式即使在原始资源较少的情况下也能保证较快的下载速度
优化设置与管理:迅雷允许用户调整下载优先级、启用UPnP支持、清理积压文件等操作,进一步提高下载性能
3、源码部分
关于 download 指令的参数
cmd\torrent\download.go
DownloadCmd.File []string
type DownloadCmd struct {
SaveMetainfos bool
Mmap bool `help:"memory-map torrent data"`
Seed bool `help:"seed after download is complete"`
Addr string `help:"network listen addr"`
MaxUnverifiedBytes *tagflag.Bytes `help:"maximum number bytes to have pending verification"`
UploadRate *tagflag.Bytes `help:"max piece bytes to send per second"`
DownloadRate *tagflag.Bytes `help:"max bytes per second down from peers"`
PackedBlocklist string
PublicIP net.IP
Progress bool `default:"true"`
PieceStates bool `help:"Output piece state runs at progress intervals."`
Quiet bool `help:"discard client logging"`
Stats bool `help:"print stats at termination"`
Dht bool `default:"true"`
PortForward bool `default:"true"`
TcpPeers bool `default:"true"`
UtpPeers bool `default:"true"`
Webtorrent bool `default:"true"`
DisableWebseeds bool
// Don't progress past handshake for peer connections where the peer doesn't offer the fast
// extension.
RequireFastExtension bool
Ipv4 bool `default:"true"`
Ipv6 bool `default:"true"`
Pex bool `default:"true"`
LinearDiscard bool `help:"Read and discard selected regions from start to finish. Useful for testing simultaneous Reader and static file prioritization."`
TestPeer []string `help:"addresses of some starting peers"`
File []string
Torrent []string `arity:"+" help:"torrent file path or magnet uri" arg:"positional"`
}
torrent中的 WebSeed 是什么
在BitTorrent协议中,WebSeed是一种扩展功能,它允许客户端从HTTP或FTP服务器下载文件的一部分或全部内容,而不仅仅是从其他对等节点(peers)获取数据。这个特性是在传统的BitTorrent下载方式之外提供了一种补充的数据来源,旨在提高下载效率和可靠性。
WebRTC 与 WebTorrent
WebRTC(Web Real-Time Communication)是一种支持网页浏览器和移动应用程序进行实时通信的技术,无需安装插件或第三方软件。它最初由Google发起,并被W3C(万维网联盟)和IETF(互联网工程任务组)标准化。WebRTC提供了一系列的API,使得开发者可以在应用中实现点对点的音视频通话、文件传输等功能。
在BitTorrent协议的应用场景下,WebTorrent是一个基于WebRTC的客户端实现,允许用户直接通过浏览器下载和共享torrent文件。这意味着使用WebTorrent,用户可以创建一个去中心化的网络,在这个网络中,用户可以直接从其他用户的浏览器下载文件片段,而不是依赖传统的集中式服务器。
WebTorrent的工作原理与传统的BitTorrent类似,但它使用了WebRTC作为底层的数据传输协议,而不是TCP/UDP。这样做的好处是,WebTorrent可以在现代浏览器环境中运行,而不需要任何额外的软件安装。由于WebRTC支持P2P连接,这使得WebTorrent能够实现在浏览器之间直接传输数据,同时保持了BitTorrent协议的效率和鲁棒性。
WebTorrent的一个典型应用场景是在网站上实现即时文件共享服务,例如Instant.io,它展示了如何在网页上实现无需等待完整下载即可播放视频或音乐的功能。此外,WebTorrent还可以用于构建分布式存储系统、去中心化应用(DApp)、科学计算等需要高效数据传输的领域。总之,WebTorrent结合了WebRTC的优势,为用户提供了一个新的方式来利用BitTorrent技术进行内容分发。
关于 metainfo
metainfo\metainfo.go
// Also known as a torrent file.
type MetaInfo struct {
InfoBytes bencode.Bytes `bencode:"info,omitempty"` // BEP 3
Announce string `bencode:"announce,omitempty"` // BEP 3
AnnounceList AnnounceList `bencode:"announce-list,omitempty"` // BEP 12
Nodes []Node `bencode:"nodes,omitempty,ignore_unmarshal_type_error"` // BEP 5
// Where's this specified? Mentioned at
// https://wiki.theory/index.php/BitTorrentSpecification: (optional) the creation time of
// the torrent, in standard UNIX epoch format (integer, seconds since 1-Jan-1970 00:00:00 UTC)
CreationDate int64 `bencode:"creation date,omitempty,ignore_unmarshal_type_error"`
Comment string `bencode:"comment,omitempty"`
CreatedBy string `bencode:"created by,omitempty"`
Encoding string `bencode:"encoding,omitempty"`
UrlList UrlList `bencode:"url-list,omitempty"` // BEP 19 WebSeeds
// BEP 52 (BitTorrent v2): Keys are file merkle roots ("pieces root"s), and the values are the
// concatenated hashes of the merkle tree layer that corresponds to the piece length.
PieceLayers map[string]string `bencode:"piece layers,omitempty"`
}
BEP 后面的数字代表文档编号。
torrent metainfo 也是分片下载的
// torrent.go
func (t *Torrent) maybeCompleteMetadata() error {
if t.haveInfo() {
// Nothing to do.
return nil
}
if !t.haveAllMetadataPieces() {
// Don't have enough metadata pieces.
return nil
}
err := t.setInfoBytesLocked(t.metadataBytes)
if err != nil {
t.invalidateMetadata()
return fmt.Errorf("error setting info bytes: %s", err)
}
if t.cl.config.Debug {
t.logger.Printf("%s: got metadata from peers", t)
}
return nil
}
启动 DHT服务以及加入DHT网络的过程
type Client struct {
dhtServers []DhtServer // 本地启动的DhtServer
}
DhtServer的实现在 github.com\anacrolix\dht\server.go
创建本地 HDT 服务并监听本地的 0.0.0.0:47176 和 [::]:47176,端口是随机分配的。然后将本地 DHT 加入到已存在的DHT网络,提供至少一个引导节点的地址,
核心函数 func (s *Server) Bootstrap()
在 anacrolix/dht 项目中 dht.go 中,提供了预置的公开的DHT节点,称为引导节点
var DefaultGlobalBootstrapHostPorts = []string{
"router.utorrent:6881",
"router.bittorrent:6881",
"dht.transmissionbt:6881",
"dht.aelitis:6881", // Vuze
"router.silotis.us:6881", // IPv6
"dht.libtorrent:25401", // @arvidn's
"dht.anacrolix.link:42069",
"router.bittorrent.cloud:42069",
}
// torrent.go
func (t *Torrent) AnnounceToDht
func (t *Torrent) dhtAnnounceConsumer
func (t *Torrent) consumeDhtAnnouncePeers
func (t *Torrent) addPeer
type Torrent struct {
peers prioritizedPeers
}
使用wireshark做个简单的抓包,udp.port == 6881
初始的引导节点:
router.utorrent:6881 ------> 108.160.166.42
router.bittorrent:6881 ------> 157.240.2.36
dht.transmissionbt:6881 ------> 212.129.33.59
dht.aelitis:6881 ------> 34.229.89.117
router.silotis.us:6881 ------> 27.19.50.246
dht.libtorrent:25401 ------> 103.252.114.11
dht.anacrolix.link:42069 ------> 51.15.69.20
router.bittorrent.cloud:42069 ------> 51.15.69.20
本文标签: 种子 网络 BitTorrent magnet DHT
版权声明:本文标题:magnet,BitTorrent,BT种子 ,DHT网络 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/b/1765660113a3402715.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论