k-buckets 数据结构是 bit-torrent 协议的一个实现细节,以便对等方足够快地回复FIND_PEERS
和FIND_VALUE
.
我在我的 kademlia 实现中所做的是将路由表保存在 python 字典中,默认情况下,我会在 5 秒内计算最近的对等点,这是我用来等待 UDP 回复的超时。为此,我需要将路由表保持在 1 000 000 个条目以下。
就像我上面说的,路由表是一个简单的 pythondict
映射peerid
到(address, port)
.
路由表存储对等点而不是值,即。不是infohash
地址。
当我收到一条FIND_PEERS
消息时,程序会回复以下代码:
async def peers(self, address, uid):
"""Remote procedure that returns peers that are near UID"""
log.debug("[%r] find peers uid=%r from %r", self._uid, uid, address)
# XXX: if this takes more than 5 seconds (see RPCProtocol) it
# will timeout in the other side.
uids = nearest(self._replication, self._peers.keys(), uid)
out = [self._peers[x] for x in uids]
return out
当我收到一条FIND_VALUE
消息时,程序会回复以下代码:
async def value(self, address, key):
"""Remote procedure that returns the associated value or peers that
are near KEY"""
log.debug("[%r] value key=%r from %r", self._uid, key, address)
out = await lookup(key)
if out is None:
# value is not found, reply with peers that are near KEY
out = nearest(self._replication, self._peers.keys(), uid)
return (b"PEERS", out)
else:
return (b"VALUE", out)
这是 的定义nearest
:
def nearest(k, peers, uid):
"""Return K nearest to to UID peers in PEERS according to XOR"""
# XXX: It only works with len(peers) < 10^6 more than that count
# of peers and the time it takes to compute the nearest peers will
# timeout after 5 seconds on the other side. See RPCProtocol and
# Peer.peers.
return nsmallest(k, peers, key=functools.partial(operator.xor, uid))
也就是说,它peers
根据它们对它们进行排序peerid
并返回k
最小的。nsmallest
应该是sort(peers, key=functools.partial(operator.xor, uid))[:k]
where uid
is a peerid
or infohash
(分别是FIND_PEERS
and FIND_VALUE
)的优化版本。
现在回到你的问题:
hashinfo 是否等同于 Mainline DHT 中的对等 ID?
hashinfo
是一个哈希值,它与peerid
ie 的哈希值相同。它们是路由表中可能的键。也就是说,torrent 文件与散列相关联,对等点与称为peerid
. 并且对等点拥有其附近的密钥的“所有权” peerid
。但是hashinfo
,如果您愿意,它不会存储在路由表或 k-buckets 中。hashinfo
存储在另一个将hashinfo
散列与其值相关联的映射中。
我问是因为这不仅仅是实现的细微差别。因为“k”在所有客户端中通常是 20 或其他整数。因此,如果我使用 k-buckets 将 torrent 文件存储为完全权限成员,我将有更少的空间来存储真实的对等数据。
这里对我在上面尝试解释的同一件事存在误解。hashinfo
是存储字典中的键。而peerid
路由表中的键又名。k-buckets 数据结构。它们都具有相同的格式,因为这就是 kademlia 路由算法的工作方式。您必须能够hashinfo
与peerid
withxor
进行比较才能判断哪些对等方“拥有”哪个hashinfo
值。
正如您在第二个片段中看到的那样,当另一个对等方请求与哈希关联的值时,它会调用lookup(key)
类似的东西,storage.get(key)
除了在我的情况下,代码将值存储在数据库中。
可能对 k-buckets 用于存储DHT 路由信息这一事实存在误解。最重要的是,torrent 协议使用 DHT 来存储torrent路由信息。
值得一提的是,qadom 的 peer.py 文件是我实现受 kademlia 启发的 DHT 的地方(除了我使用 256 位哈希和放弃alpha
和k
参数并使用单个REPLICATION
参数)。该代码大部分时间都在检查测试。
另外,我从另一个项目中获得灵感,叫做简单的 kademlia,它(尝试?)实现 k-buckets。
据我了解,Torrent DHT 路由看起来像qadombag
功能,除了接收对等方必须对公告进行身份验证,而在 qadom 中,包是免费的。
另外,请查看原始的 kademlia 论文。