func (p *Peer) GetValue(key []byte) ([]byte, bool) {
hashedKey := sha1.Sum(key)
if !bytes.Equal(hashedKey[:], p.node.id[:]) { // 如果当前节点不是key对应的节点,则继续查找更接近目标id的其他节点。
targetId := sha1.Sum(key)
closestPeers := make([]Peer, 0, PeerCount2)
closestPeers = append(closestPeers, p.neighbors...)
closestPeers = p.dht.findClosestPeers(targetId, PeerCount-len(p.neighbors), closestPeers)
for _, peer := range closestPeers {
value, ok := peer.GetValue(key) // 递归调用GetValue函数,在最近的num个节点中查找键值对。
if ok {
return value, true
}
}
return nil, false // 所有最近的num个节点都没有找到该键值对,返回false。
}
if value, ok := p.values[string(key)]; ok { // 如果当前节点包含该键值对,则返回其对应的value和true。
return value, true
}
return nil, false // 当前节点中不存在该键值对,返回false。
}
// 将自身添加到距离目标id更近的某个Peer的邻居列表中,并将该Peer添加到自己的邻居列表中。 func (p *Peer) addNeighbor(peer *Peer) {
if len(p.neighbors) < 2 { // 如果邻居数量小于2,则直接添加到邻居列表中并返回。
p.neighbors = append(p.neighbors, peer)
return
}
if p.neighbors[0].node.id == peer.node.id || p.neighbors[1].node.id == peer.node.id { // 如果该节点已经是当前节点的邻居,则直接返回。
return
}
targetId := peer.node.id
selfDist := distance(selfNodeId, targetId)
neighborDist1 := distance(p.neighbors[0].node.id, targetId)
neighborDist2 := distance(p.neighbors[1].node.id, targetId)
if selfDist < neighborDist1 && selfDist < neighborDist2 { // 如果当前节点离目标id更近,则将其添加到peer的邻居列表中,并将peer添加到自己的邻居列表中。
peer.addNeighbor(p)
p.neighbors = append(p.neighbors[:], peer)
} else if neighborDist1 < neighborDist2 { // 否则,选择距离目标id更近的邻居节点,将其替换为新节点。
p.neighbors[0] = peer
} else {
p.neighbors[1] = peer
}
}
// 将指定Peer从邻居列表中移除。 func (p *Peer) removeNeighbor(peer *Peer) {
for i, n := range p.neighbors {
if n.node.id == peer.node.id {
copy(p.neighbors[i:], p.neighbors[i+1:])
p.neighbors[len(p.neighbors)-1] = nil
p.neighbors = p.neighbors[:len(p.neighbors)-1]
break
}
}
}
// 找到包含指定ID的桶,并从其中删除指定ID的节点。如果找不到对应的桶或者未找到对应的节点,则返回false。 func (dht *DHT) removeNode(id [IdSize]byte) bool {
bucketPos := distance(selfNodeId, id)
bucket := dht.getBucket(bucketPos)
if bucket.RemoveNode(id) { // 如果当前节点所在的桶中存在指定ID的节点,则直接删除并返回true。
return true
}
closestPeers := make([]*Peer, 0, PeerCount2)
for _, n := range bucket.nodes { // 否则,将该桶中所有距离目标id更近的节点添加到closestPeers列表中。
if bytes.Equal(n.id[:], selfNodeId[:]) {
continue
}
closestPeers = append(closestPeers, &Peer{
dht: dht,
node: n,
values: make(map[string][]byte),
neighbors: nil,
})
}
targetId := id
closestPeers = dht.findClosestPeers(targetId, PeerCount-len(closestPeers), closestPeers)
for _, peer := range closestPeers { // 遍历closestPeers列表,递归调用removeNode函数,在最近的num个节点中查找并删除对应的节点。
if peer.removeNode(id) {
return true
}
}
return false // 所有最近的num个节点都没有找到对应的节点,则返回false。
}