BitTorrent DHT 商中文翻译

前言

召开了一个重力链接和BT种子的追寻引擎 {Magnet &
Torrent},因此拿
DHT 协议还看了相同普。

原文:DHT
Protocol
译文:BitTorrent DHT
磋商中文翻译

BitTorrent 以”分布式哈希表”(DHT)来啊无 tracker 的种子(torrents)存储
peer 之间的联络信息。这样每个 peer 都成了 tracker。这个协议基于
Kademila[1] 网络以于 UDP 上落实。

央留意本文档中使用的术语,以免混乱。

  • “peer” 是以一个 TCP 端口上监听的客户端/服务器,它实现了 BitTorrent
    协议。

  • “节点” 是以一个 UDP 端口上监听的客户端/服务器,它实现了
    DHT(分布式哈希表) 协议。

DHT 由节点组成,它存储了 peer 的位置。BitTorrent 客户端包含一个 DHT
节点,这个节点用来维系 DHT 中另外节点,从而获取 peer 的职务,进而通过
BitTorrent 商谈下载。

原题共有如下3粗开,底下一一作答:

概述 Overview

每个节点有一个大局唯一的标识符,作为 “node ID”。节点 ID 是一个擅自选择的
160bit 空中,BitTorrent infohash[2] 也使这样的 160bit 空间。

“距离”用来比少单节点 ID 之间或者节点 ID 和 infohash
之间的”远近”。节点必须维护一个路由表,路由于表中蕴藏一部分任何节点的联络信息。其它节点距离自己更走近时,路由于表信息更加详细。因此每个节点都了解
DHT 中离自己不行”近”的节点的关系信息,而离开自己很多之 ID
的沟通信息可亮的百般少。

每当 Kademlia
网络被,距离是通过异或(XOR)计算的,结果为无符号整数。distance(A, B) = |A xor B|,值更聊表示进一步凑。

当节点要为 torrent 寻找 peer 时,它将自己路由于表中的节点 ID 和 torrent 的
infohash 进行”距离比”。然后往程由于表中离 infohash
最近底节点发送请求,问它在下载者 torrent 的 peer
的牵连信息。如果一个于联系的节点知道下载者 torrent 的 peer 信息,那个
peer
的维系信息用给还原给当下节点。否则,那个让联系的节点则必须回复在她的路由表中去该
torrent 的 infohash 最近底节点的牵连信息。最初的节点重复地伸手于目标
infohash
更近之节点,直到不可知重新找到更靠近的节点为止。查询了了后头,客户端将好看做一个
peer 插入到拥有回复节点中离种子最近底充分节点受到。

恳请 peer
的返值包含一个免透明底价值,称之为”令牌(token)”。如果一个节点宣布她所主宰的
peer
正在下载一个米,它必须在回复请求节点的又,附加上对方为我们发送的近年底”令牌(token)”。这样当一个节点试图”宣布”正在下载一个粒时,被求的节点核对令牌和出呼吁的节点的
IP
地址。这是为着防止恶意之主机登记其它主机的米。由于令牌仅仅由要节点返回给接令牌的平个节点,所以没确定外的有血有肉落实。但是令牌必须在一个规定的工夫外给纳,超时后叫牌则失效。在
BitTorrent 的兑现着,token 是于 IP 地址后连接一个
secret(可以说是一个随机数),这个 secret 每五分钟转同样不成,其中 token
在老钟以内是不过承受之。

1.争评论昨晚发布之PC版微信?(产品目标、界面、功能等)

产品目标:Windows版微信的目标是许以PC端使用微信进行再次安定、顺畅和容错性更好(与Web版相比)的简报功能,是于微信的应用平台的一个分外选项。
PC端微信的产出保证了用户以利用PC时微信及信息的“即经常”性,避免了是因为走端微信及发出新消息造成对PC持续性使用的阻隔。说到底还是为了保“即时通讯”产品的真相。
界面:和Web版微信基本一致。
效益:主要是简简单单的“通讯”和“联系人”模块,也基本和Web版微信一样。
PS:PC版微信在了一个“备份聊天记录”的职能,终于不再单独是必时间之云端存储了。对聊天记录的垂青程度有矣增强。可能吗是微信“变再”的启。

路由表 Routing Table

诸一个节点维护一个路由表保存已解之好节点。路由表中的节点是故来当以 DHT
中求的起始点。路由表中的节点是当不停的通往外节点请求过程中,对方节点回复的。

连无是咱于求过程中收受得节点都是如出一辙的,有的节点是好之,而另一对虽说非是。许多应用
DHT
协议的节点都可发送请求并收受过来,但是非克主动过来其他节点的伸手。节点的路由表只含有已掌握之好节点,这可怜重大。好节点是指以过去底
15
分钟内,曾经针对我们的某一个呼吁让起过卷土重来的节点,或者已对我们的呼吁被来过一个过来(不用在15分钟里),并且以过去的
15 分钟为我们发送了要。上述两种状况都可拿节点视为好节点。在 15
分钟之后,对方没有上述 2
种情况时有发生,这个节点将改成可疑的。当节点不能够给咱的等同层层请求让来回复时,这个节点将成坏之。相比那些不为人知状态的节点,已清楚的好节点会叫为吃复强的事先级。

路由表覆盖于 0 到 2^160 全部的节点 ID
空间。路由表又为细分也桶(桶s),每个桶包含部分的 ID
空间。空的路由表只发一个桶,它的 ID 范围从 min=0 到 max=2^160。当 ID 为
N 的节点插入到表中时,它将为安放 ID 范围以 min <= N < max 的 桶
中。空的路由表只发生一个桶所以所有的节点都用吃坐这个桶中。每一个桶顶多只能保留
K 个节点,当前
K=8。当一个桶放满了好节点之后,将不再允许新的节点加入,除非我们自身之节点ID在斯桶的范围外。在这样的动静下,这个桶将给分裂为
2
独新的桶,每一个新桶的限制都是本来旧桶的一半。原来旧桶中之节点将让重新分配到当下点儿独新的桶中。如果一个新表只发生一个桶,这个蕴藏全体范围之桶将总为分裂为
2 独新的桶,第一个之覆盖范围从 0..2^159 和 2159..2160。

当桶装满了好节点,新的节点会让抛弃。一旦桶中之某一个节点变为了老的节点,那么我们就用新的节点来替换这个老的节点。如果桶中出以
15
分钟内还无活跃了的节点,我们用这么的节点视为可疑的节点,这时我们通往最久没有联络的节点发送
ping。如果吃 ping 的节点给起了还原,那么我们往下一个可疑的节点发送
ping,不断这样循环下去,直到有有一个节点没有被出 ping
的东山再起,或者手上桶中之享有节点都是好的(也就算是怀有节点都未是可疑节点,他们在过去
15 分钟内都起运动)。如果桶中的某某节点没有对准我们的 ping
给有回复,我们最好好再试一次(再发送一蹩脚
ping,因为这节点可能仍是生动活泼的,但出于网络不通,所以来了废除包现象,注意
DHT 的保证都是 UDP
的),而无是就抛弃这个节点还是直接用新节点来替她。这样,我们得路由于表将充满稳定之丰富时在线的节点。

各一个桶都应保持一个 lastchange
字段来表明桶中节点的”新鲜”度。当桶着之节点被 ping
并被来了恢复,或者一个节点被加入到了桶,或者一个节点被一个新的节点所取代,桶的
lastchange 字段都应该被更新。如果一个桶的 lastchange 在过去之 15
分钟内且未曾转变,那么我们用履新她。这个更新桶操作是如此形成的:从夫桶所覆盖的克中随心所欲挑选一个
ID,并对准这 ID 执行 find_nodes
查找操作。常常接到请求的节点通常不需时更新自己的桶,反之,不经常接到请求的节点常常要周期性的尽更新所有桶的操作,这样才会确保当我们因而到
DHT 的时候,里面来足多之好的节点。

以插入第一独节点到路由表并启动服务后,这个节点应试着寻找 DHT
中离自己再接近之节点,这个查找工作是透过持续的发 find_node
消息让更接近的节点来就的,当不克找到更近乎的节点时,这个扩散工作便了了。路由表应当吃启动工作跟客户端软件保存(也即是启动之上起客户端挨读取路由表信息,结束之时段客户端软件记录到文件被)。

2.会对QQ造成威胁为?

脚下总的来说微信是无力回天替代QQ的,好于发送文书之类的众多效微信上还并未。
可是威胁是肯定有的。
由于微信的启幕平台是手机端,注定了外是一个适用于运动端的,比较“轻量级”的出品。但是通过一段时间的版迭代创新,移动端微信的“体积”与效能已经越来越庞大与复杂。
本运动版QQ的作用微信为多数还发生矣。

BitTorrent 协和扩展 BitTorrent Protocol Extension

BitTorrent 商已经被扩张为好当经 tracker 得到的 peer
之间互相交换节点的 UDP 端口号(也即是报对方我们的 DHT
服务端口号),在这么的办法下,客户端可由此下载普通的种子文件来机关扩展
DHT 路由表。新装置之客户端第一破试着下载一个无 tracker
的种子时,它的路由表中将没有任何节点,这是它们用以 torrent
文件被找到联系信息。

peers 如果支持 DHT 商事就以 BitTorrent 协议握手消息之保留位的第 8
字节的末段一位置为 1。这时要 peer 收到一个 handshake 表明对方支持
DHT 商,就相应发送 PORT 信。它由字节 0x09 开始,payload 的长是
2 独字节,包含了此 peer 的 DHT 服务以的网配节序的 UDP 端口号。当
peer 收到这么的音是当向对方的 IP 和信息遭指定的捧口号的节点发送
ping。如果接受了 ping
的东山再起,那么该使用上述的点子将新节点的联络信息在到路由表中。

3.会成为开机启动项也?

自家之报是:不见面。
题主表述不是大了解,我哪怕将该解成是否无需手机微信在线即可登录PC端微信来设想。
手机是现阶段微信下平台的必项,而PC只是一个额外平台选择,不是一个好允许微信独立存在的平台。所以任何平台的微信还是坐手机端的微信扩展起来来的。
除此以外,PC版微信登录离不开手机版微信,实际上是微信想只要直“粘”着您的运动装备,不让你关掉它,不为你扔手机端微信的可能。
因此一方面是保障比较高的“即经常”性,另一方面是维系移动端占有率。出于这点儿独因,腾讯是匪会见同意无需手机微信在线即可登录PC端微信的。

Torrent 文件扩展 Torrent File Extensions

一个无 tracker 的 torrent 文件字典不带有 announce 关键字,而下一个
nodes 关键字来代表。这个主要字对应的情应该设置也 torrent
创建者的路由表中 K
个最好相近的节点。可供应选择的,这个根本字呢得安装为一个已解之可用节点,比如这个
torrent 文件之创立者。请不要自行进入 router.bittorrent.com 到 torrent
文件中或电动进入此节点到客户端路由表中。

nodes = [["", ], ["", ], ...]

nodes = [["127.0.0.1", 6881], ["your.router.node", 4804]]

KRPC协议 KRPC Protocol

KRPC 协议是由 bencode 编码组成的一个简易的 RPC 结构,他采用 UDP
报文发送。一个独门的恳求保管吃起去然后一个独立的承保被还原。这个协议没有重发。它涵盖
3 种植信息:请求,回复与左。对DHT协议而言,这里有 4
种请求:pingfind_nodeget_peersannounce_peer

相同漫漫 KRPC 消息由一个独的字典成,其中有 2
单第一字是具备的音讯还饱含的,其余的附加重大字在消息类型。每一个信还带有
t 关键字,它是一个表示了 transaction ID 的字符串类型。transaction ID
由请求节点产生,并且恢复中而含有回显该字段,所以回复可能对应一个节点的大多独请求。transaction
ID 应当给编码为一个少的次向前制字符串,比如 2 独字节,这样虽可针对应 2^16
单请求。另一个每个 KRPC 消息还带有的重要字是
y,它由一个字节组成,表明这信息之档次。y 对应之价有三栽情况:q
表示求,r 表示恢复,e 表示错误。

联系信息编码 Contact Encoding

Peers 的维系信息被编码为 6 字节的字符串。又被称为
“CompactIP-address/port info”,其中前 4 单字节是网配节序的 IP 地址,后
2 独字节是网络配节序的端口。

节点的关系信息于编码为 26 字节的字符串。又受称为 “Compactnode
info”,其中前 20 字节是网络配节序的节点 ID,后面 6 个字节是 peers 的
“CompactIP-address/port info”。

请求 Queries

恳请,对诺受 KPRC 信字典中之 y 关键字之价是 q,它含有 2
个叠加的机要字 qa。关键字 q
是一个字符串类型,包含了请的办法名字。关键字 a
一个字典类型涵盖了请求所附加的参数。

回复 Responses

复原,对许为 KPRC 音字典中的 y 关键字的价值是
r,包含了一个附加的第一字 r。关键字 r
是一个字典类型,包含了归来的价值。发送过来消息是在是解析了央消息的功底及落成的。

错误 Errors

谬误,对许被 KPRC 信字典中之 y 关键字的价值是
e,包含一个叠加的首要字 e。关键字e`
是一个列表类型。第一单因素是一个数字型,表明了错误码。第二个因素是一个字符串类型,表明了错误信息。当一个请不能够分析或错时,错误包将给发送。下表描述了或者出现的错误码:

错误码 描述
201 一般错误
202 服务错误
203 协议错误,比如不正规的保,无效的参数,或者失实的 token
204 未知方法

荒谬包例子 Example Error Packets:

generic error = {"t":"aa", "y":"e", "e":[201, "A Generic Error Ocurred"]}

bencoded = d1:eli201e23:A Generic Error Ocurrede1:t2:aa1:y1:ee

DHT 请求 DHT Queries

有的请求都含一个主要字 id,它涵盖了请求节点的节点
ID。所有的东山再起也包含关键字id,它涵盖了还原节点的节点 ID。

ping

无限基础的求虽是 ping。这时 KPRC 协议被之 "q" = "ping"。Ping
请求包含一个参数 id,它是一个 20
字节的字符串包含了发送者网络配节序的节点 ID。对应之 ping
回复也暗含一个参数 id,包含了回复者的节点 ID。

  • 参数: {"id" : ""}

  • 回复: {"id" : ""}

报文包例子 Example Packets

ping Query = {"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}}
bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe
Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}
bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re

find_node

find_node 被用来搜寻给定 ID 的节点的关系信息。这时 KPRC 协议被的
"q" == "find_node"find_node 请求包含 2 单参数,第一只参数是
id,包含了请节点的ID。第二只参数是
target,包含了请求者正在摸索的节点的 ID。当一个节点接收至了
find_node 的乞求,他应让有相应之东山再起,回复中寓 2 只根本字 id
nodesnodes
是一个字符串类型,包含了为呼吁节点的路由表中极其相仿目标节点的 K(8)
个极端接近的节点的联络信息。

  • 参数: {"id" : "", "target" : ""}
  • 回复: {"id" : "", "nodes" : ""}

报文包例子 Example Packets

find_node Query = {"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456"}}

bencoded = d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe

Response = {"t":"aa", "y":"r", "r": {"id":"0123456789abcdefghij", "nodes": "def456..."}}

bencoded = d1:rd2:id20:0123456789abcdefghij5:nodes9:def456...e1:t2:aa1:y1:re

get_peers

get_peers 与 torrent 文件之 infohash 有关。这时 KPRC 协议被之
"q" = "get_peers"get_peers 请求包含 2 独参数。第一个参数是
id,包含了要节点的 ID。第二个参数是 info_hash,它代表 torrent
文件之 infohash。如果为求的节点有对应 info_hash
peers,他拿返回一个要害字
values,这是一个列表类型的字符串。每一个字符串包含了
"CompactIP-address/portinfo" 格式的 peers
信息。如果吃求的节点没有这 infohash 的 peers,那么他拿回关键字
nodes,这个关键字含了为请节点的路由表中离 info_hash 最近的 K
个节点,使用 "Compactnodeinfo" 格式回复。在及时点儿栽情景下,关键字
token 都将给归。token 关键字在事后的 annouce_peer
请求中务必要带走。token 是一个少的亚迈入制字符串。

  • 参数:
    {"id" : "", "info_hash" : "<20-byte infohash of target torrent>"}
  • 回复: {"id" : "", "token" :"", "values" : ["", ""]}
  • 或: {"id" : "", "token" :"", "nodes" : ""}

报文包例子 Example Packets:

get_peers Query = {"t":"aa", "y":"q", "q":"get_peers", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456"}}

bencoded = d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe

Response with peers = {"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "values": ["axje.u", "idhtnm"]}}

bencoded = d1:rd2:id20:abcdefghij01234567895:token8:aoeusnth6:valuesl6:axje.u6:idhtnmee1:t2:aa1:y1:re

Response with closest nodes = {"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "nodes": "def456..."}}

bencoded = d1:rd2:id20:abcdefghij01234567895:nodes9:def456...5:token8:aoeusnthe1:t2:aa1:y1:re

announce_peer

以此请用来表明发出 announce_peer 请求的节点,正在某个端口下载
torrent 文件。announce_peer 包含 4 个参数。第一单参数是
id,包含了要节点的 ID;第二单参数是 info_hash,包含了 torrent
文件之 infohash;第三单参数是 port 包含了整型的端口号,表明 peer
在谁端口下载;第四独参数数凡 token,这是在前的 get_peers
请求中收的过来中带有的。收到 announce_peer 请求的节点必须检查是
token 与之前我们还原给这个节点 get_peerstoken
是否一致。如果相同,那么让求的节点将记录发送 announce_peer 节点的 IP
和请被蕴含的 port 端口号在 peer 联系信息中对应之 infohash 下。

参数:

{
"id" : "",
"implied_port": <0 or 1>,
"info_hash" : "<20-byte infohash of target torrent>",
"port" : ,
"token" : ""
}

回复: {"id" : ""}

报文包例子 Example Packets:

announce_peers Query = {"t":"aa", "y":"q", "q":"announce_peer", "a": {"id":"abcdefghij0123456789", "implied_port": 1, "info_hash":"mnopqrstuvwxyz123456", "port": 6881, "token": "aoeusnth"}}

bencoded = d1:ad2:id20:abcdefghij01234567899:info_hash20:

mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe

Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}

bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re

References

  • [1] Peter Maymounkov, David Mazieres, “Kademlia: A Peer-to-peer
    Information System Based on the XOR Metric”, IPTPS 2002.

  • [2] Use SHA1 and plenty of entropy to ensure a unique ID.

Copyright

This document has been placed in the public domain.