代码拉取完成,页面将自动刷新
同步操作将从 元谷/pydht 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
# -*- coding: cp936 -*-
#去除节点表的维护
#去除ping等不实用的协议实现
import socket,select,time,logging
from utils import random_node_id, get_version,encode_nodes,decode_nodes
from bencode import bencode,bdecode
class DHT:
def __init__(self, hashSet):
self.port = 6219
self.host = '0.0.0.0'
self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.s.setblocking(False)
#set option reused
self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR , 1)
self.s.bind((self.host, self.port))
self.id = random_node_id()
self.findNodesNum = 0
self.findNodesTime = 0
self.htable = [] #一个小型的路由表
self.hashSet = hashSet #一个存放文件hash的表
def __send(self, message, address):
message["v"] = get_version()
encoded = bencode(message)
self.s.sendto(encoded, address)
def __epoll(self):
inputs = [self.s]
outputs = []
timeout = 15
readable , writable , exceptional = select.select(inputs, outputs, inputs, timeout)
# When timeout reached , select return three empty lists
if not (readable or writable or exceptional) :
print "Time out ! "
self.__boot()
return;
for s in readable :
if s:
try:
string, address = self.s.recvfrom(1024)
self.__handler(string, address)
except:
return
def __handler(self, data, address):
message = bdecode(data)
if message["y"] == "q":
if message["q"] == "ping":
print 'pong', address
self.__pong(message, address)
if message["q"] == "find_node":
print 'found_node', address
self.__fond_node(message, address)
if message['q'] == "get_peers":
print 'got_peers', address
self.__got_peers(message, address)
if message['q'] == "announce_peer":
print 'announced_peer', address
self.__announced_peer(message, address)
if message["y"] == "r":
if message['t'] == "find_node":
self.__find_node_respond(message, address)
def __pong(self, message, address):
""" Construct reply message for ping """
message = {
"y": "r",
"r": {
"id": self.id
},
"t":message['t']
}
self.__send(message, address)
def __fond_node(self, message, address):
message = {
"y": "r",
"r": {
"id": self.id,
"nodes": message['a']['id']
},
"t":message['t']
}
self.__send(message, address)
def __got_peers(self, message, address):
"""在这里可以把nodes全写上自己的ip和port,好处是可以增加节点收录的概率。但是代价是,获得同一个节点的多次相同请求"""
message = {
"y": "r",
"r": {
"id": self.id,
"nodes": encode_nodes(self.htable)
} ,
"t":message['t']
}
self.__send(message, address)
def __announced_peer(self, message, address):
info_hash = message["a"]['info_hash'].encode("HEX").upper()
print 'infohash' + info_hash
self.hashSet.put(info_hash)
message = {
"y": "r",
"r": {
"id": self.id,
} ,
"t":message['t']
}
self.__send(message, address)
def __find_node(self, address):
""" Construct query find_node message """
print "find_node", address
message = {
"y": "q",
"q": "find_node",
"a": {
"id": self.id,
"target": random_node_id()
},
"t":'find_node'
}
self.__send(message, address)
def __find_node_respond(self, message, adress):
print 'find_node_respond'
if len(self.htable) < 8:
node = (message['r']['id'], {'host':adress[0], 'port':adress[1]})
self.htable.append(node)
else:
self.htable[self.findNodesNum%8] = (message['r']['id'], {'host':adress[0], 'port':adress[1]})
self.findNodesNum = self.findNodesNum + 1
if self.findNodesNum > 1000: #如果一直在寻找节点,带宽消耗比较大
return
nodes = decode_nodes (message['r']['nodes'])
for idn, host, port in nodes:
self.__find_node((host,port)) #根据返回的节点继续寻找节点
def __boot(self):
if len(self.htable) > 0:
for node in self.htable:
self.__find_node((node[1]['host'], node[1]['port']))
self.__find_node((self.boothost, self.bootport))
else:
for i in range(3):
self.__find_node((self.boothost, self.bootport))
self.findNodesNum = 0
self.findNodesTime = time.time()
def start(self, boothost, bootport):
self.boothost = boothost
self.bootport = bootport
while 1:
if self.findNodesTime == 0 or time.time() - self.findNodesTime > 60: #每一分钟,搜索一次节点。每次搜索100个节点
self.__boot()
self.__epoll()
'''
d = DHT()
d.start('router.bittorrent.com', 6881)
'''
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。