<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>分布式散列表 &#8211; 寂静花园</title>
	<atom:link href="https://www.addesp.com/archives/tag/%E5%88%86%E5%B8%83%E5%BC%8F%E6%95%A3%E5%88%97%E8%A1%A8/feed" rel="self" type="application/rss+xml" />
	<link>https://www.addesp.com</link>
	<description>寂静中交织着热情</description>
	<lastBuildDate>Tue, 18 Jan 2022 10:45:51 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.2</generator>
	<item>
		<title>BitTorrent 分布式散列表（DHT）协议详解</title>
		<link>https://www.addesp.com/archives/5428</link>
					<comments>https://www.addesp.com/archives/5428#respond</comments>
		
		<dc:creator><![CDATA[ADD-SP]]></dc:creator>
		<pubDate>Sat, 16 Oct 2021 15:26:02 +0000</pubDate>
				<category><![CDATA[BitTorrent 协议簇详解]]></category>
		<category><![CDATA[分布式散列表]]></category>
		<category><![CDATA[通信协议]]></category>
		<guid isPermaLink="false">https://www.addesp.com/?p=5428</guid>

					<description><![CDATA[DHT 协议大幅度提高了 BitTorrent 网络的容错性，使整个网络难以因 Tracker 服务器的下线而崩溃，而这一切的外在表现就是“磁力链接”。]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">概述</h2>



<p class="wp-block-paragraph">DHT 协议大幅度提高了 BitTorrent 网络的容错性，使整个网络难以因 Tracker 服务器的下线而崩溃，而这一切的外在表现就是“磁力链接”。</p>



<p class="wp-block-paragraph">DHT 协议涉及到分布式散列表的相关知识，请参考<a href="/archives/5338" target="_blank" rel="noreferrer noopener" title="/archives/5338">分布式散列表协议 —— Kademlia 详解</a>。</p>



<p class="wp-block-paragraph">下文将 ”BitTorrent 软件“ 简称为 &#8220;BT 软件“。</p>



<h2 class="wp-block-heading">为什么需要 DHT 协议？</h2>



<p class="wp-block-paragraph"><a href="/archives/5271" target="_blank" rel="noreferrer noopener" title="/archives/5271">伙伴（Peer）协议</a>可以让 BitTorrent 节点之间互相交换已知信息来完整下载和上传。当然这一切的前提是我们能够知道其它节点的联系方式，没有了这个前提，我们只能以 0KB/s 的速度等待了。<a href="/archives/5271" target="_blank" rel="noreferrer noopener" title="/archives/5271">Tracker 协议</a>用于查询可以帮助下载和上传的节点，有了节点的联系方式我们才能通过伙伴（Peer）协议来交换数据完成下载和上传。但是 Tracker 是一个中心的服务器，一旦 Tracker 服务器下线，那么网络中的所有节点就只能抓瞎了。</p>



<p class="wp-block-paragraph">可见 Tracker 服务器是整个 BitTorrent 网络的弱点，究其本质其实是因为节点的联系方式都存储在一个固定的位置，容错性很差。如果将这些信息存储在整个 BitTorrent 网络中，那么少数节点的故障并不会导致联系方式的丢失，也就不会影响整个网络的运行。这就是 DHT 协议的任务 —— 将每个节点变成一个小型 Tracker。</p>



<h2 class="wp-block-heading">磁力链接</h2>



<p class="wp-block-paragraph">当你使用 BT 软件下载的时候你可能见过下面这样的地址。</p>



<pre class="wp-block-code language-URL"><code>magnet:?xt=urn:btih:c9e15763f722f23e98a29decdfae341b98d53056&amp;dn=Cosmos+Laundromat&amp;tr=udp%3A%2F%2Fexplodie.org%3A6969&amp;tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&amp;tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&amp;tr=udp%3A%2F%Ftracker.leechers-paradise.org%3A6969&amp;tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&amp;tr=wss%3A%2F%2Ftracker.btorrent.xyz&amp;tr=wss%3A%2F%2Ftracker.fastcast.nz&amp;tr=wss%3A%2F%2Ftracker.openwebtorrent.com&amp;ws=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2F&amp;xs=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2Fcosmos-laundromat.torrent</code></pre>



<p class="wp-block-paragraph">看起来很长，其实这个链接可以简化。</p>



<pre class="wp-block-code language-url"><code>magnet:?xt=urn:btih:c9e15763f722f23e98a29decdfae341b98d53056</code></pre>



<p class="wp-block-paragraph">严格来说上面的已经是最简版本了，但是对于现在的 BT 软件，如果你输入一个含有 40 个十六进制字符的字符串，它会自动帮你转为磁力链接。</p>



<pre class="wp-block-code language-url"><code>c9e15763f722f23e98a29decdfae341b98d53056</code></pre>



<p class="wp-block-paragraph">所以说最重要的就是这个十六进制字符串。你可以把用你的 BT 软件下载这段字符串，下载下来的视频还挺有趣的。</p>



<p class="wp-block-paragraph">上面这段十六进制字符串是通过哈希算法生成，每份资源丢到哈希算法里都会得到这样的一个字符串，并且仅属于这份资源（大概），也就是我们在之前的系列文章中提到的 <code>info_hash</code>。</p>



<h2 class="wp-block-heading">工作流程</h2>



<p class="wp-block-paragraph">当节点上线时它会随机生成一个节点 ID 并作为自己的 ID 使用。</p>



<p class="wp-block-paragraph">初始状态下我们并不知道其它节点的联系方式，此时需要通过其它方式或者，比如 Trakcer 服务器，或者 <code>.torrent</code> 文件中写明的联系方式。</p>



<p class="wp-block-paragraph">然后我们会与节点建立联系并构建路由表，并周期性地测试节点的联通状态，比如通信时延。通过此种方式我们获得了一个通信质量良好的节点列表。这时伙伴交换（Peer Exchange）协议也开始工作，我们会和越来越多的节点建立联系。</p>



<p class="wp-block-paragraph">当我们想下载一个文件时，我们计算文件 ID 和已知节点之间的距离，从自己的路由表中选择距离最近的若干个节点发起查询请求，接收到请求的节点如果正好可以提供这个文件则可以直接开始下载，反之它们会从自己的路由表中选择距离最近的若干个节点返回。</p>



<p class="wp-block-paragraph">当我们向上传某些文件时（做种），我们会计算文件的 ID，然后将自己的联系方式存储到距离文件 ID 最近的若干个节点中。</p>



<h3 class="wp-block-heading">人话</h3>



<p class="wp-block-paragraph">我们做种时总会把自己的联系方式存储到一个很小的范围内，此范围由文件的 ID 决定。当我们想下载时，会根据文件 ID 计算出这个范围，然后从里找做种的人就行了。</p>



<h2 class="wp-block-heading">协议概述</h2>



<p class="wp-block-paragraph">DHT 协议是一个基于 <a href="/archives/5338" target="_blank" rel="noreferrer noopener" title="/archives/5338">Kademila 协议</a>并使用 UDP 传输的应用协议，它可以将每个节点变成一个小型 Tracker，避免中心化的 Tracker 服务器所带来的风险。</p>



<p class="wp-block-paragraph">DHT 协议的基础部分和  <a href="/archives/5338" target="_blank" rel="noreferrer noopener" title="/archives/5338">Kademila 协议</a>一致，比如节点的 ID 都是 160 位的二进制数，使用异或算法计算距离和使用相同方法构建路由表。不同的地方在于 DHT 协议更改了部分 RPC 过程，并将这些 RPC 集合命名为 KRPC 协议。</p>



<h2 class="wp-block-heading">KRPC 协议</h2>



<p class="wp-block-paragraph">KRPC 协议是一个由 UDP 数据包和其包裹的经过 B 编码字典组成的简洁的 RPC 协议。每次查询只会有一次响应，没有重发/重试这种机制。</p>



<p class="wp-block-paragraph">下面是三种消息类型。</p>



<ul class="wp-block-list"><li>query（查询）</li><li>response（响应）</li><li>error（错误）</li></ul>



<p class="wp-block-paragraph">下面是四类查询。</p>



<ul class="wp-block-list"><li>ping</li><li>find_node</li><li>get_peer</li><li>announce_peer</li></ul>



<p class="wp-block-paragraph">KRPC 消息是一个经过 B 编码的字典（dictionary），每个消息至少有三个 key，分别表示”事务 ID“、”消息类型“ 和 ”客户端名称和版本“。根据消息的不同可以有更多的 key。</p>



<h3 class="wp-block-heading">ping</h3>



<p class="wp-block-paragraph">此消息用于检查目标节点的状态，发起者应发送自己的节点 ID，接收者应回复自己的节点 ID。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>喂？听到了么？</p><p>听到了。</p></blockquote>



<h3 class="wp-block-heading">find_node</h3>



<p class="wp-block-paragraph">此消息用于查询指定节点的联系方式（IP 地址和端口），发起者发送目标节点的 ID，接收者会从自己的路由表中选出距离目标节点最近的 k 个节点 ID 并返回。这是一个递归的过程，详情请阅读<a href="/archives/5338" target="_blank" rel="noreferrer noopener" title="/archives/5338">分布式散列表协议 —— Kademlia 详解</a>。</p>



<h3 class="wp-block-heading">get_peers</h3>



<p class="wp-block-paragraph">此消息用于查询于指定的 <code>info_hash</code> 相关的节点的联系方式，功能类似 Trakcer 服务器。发起者应发送 <code>info_hash</code>，接收者应返回与 <code>info_hash</code> 有关的节点列表，如果接收者不知道哪些节点于 <code>info_hash</code> 有关，则从自己的路由表中选出 k 个距离 <code>info_hash</code> 最近的节点并返回。</p>



<h3 class="wp-block-heading">announce_peer</h3>



<p class="wp-block-paragraph">当一个节点于某个 <code>info_hash</code> 有关时（下载或上传），它应当发起此消息。发起者应发送自己的节点 ID、<code>info_hash</code> 和监听端口。接收者应存储接收到的联系方式，将 <code>info_hash</code> 和联系方式关联起来，用于响应 get_peers 消息。</p>



<h2 class="wp-block-heading">参考资料</h2>



<p class="wp-block-paragraph"><a href="https://www.bittorrent.org/beps/bep_0005.html" target="_blank" rel="noreferrer noopener" title="https://www.bittorrent.org/beps/bep_0005.html">DHT Protocol</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.addesp.com/archives/5428/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
