13 Star 26 Fork 10

元谷 / pydht

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
pydht.py 5.45 KB
一键复制 编辑 原始数据 按行查看 历史
元谷 提交于 2014-02-13 22:53 . 加快种子来源
# -*- 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)
'''
Python
1
https://gitee.com/yuangu/pydht.git
git@gitee.com:yuangu/pydht.git
yuangu
pydht
pydht
master

搜索帮助