用XML_RPC实现P2P
- 作者: 嗨丶小公主快出来嘿嘿嘿
- 来源: 51数据库
- 2022-08-12
# -*- coding: utf-8 -*-
from xmlrpclib import ServerProxy, Fault
from os.path import join, isfile, abspath
from SimpleXMLRPCServer import SimpleXMLRPCServer
from urlparse import urlparse
import sys
import xmlrpclib
SimpleXMLRPCServer.allow_reuse_address = 1
#避免循环请求和长链请求。之所以用6是采用了六度分隔的原理
MAX_HISTORY_LENGTH = 6
UNHANDLED = 100
ACCESS_DENIED = 200
class UnhandledQuery(Fault):
def __init__(self, message="Counldn't handle the query"):
Fault.__init__(self, UNHANDLED, message)
class AccessDenied(Fault):
def __init__(self, message='Access denied'):
Fault.__init__(self, ACCESS_DENIED, message)
def inside(dirs, name):
the_dir = abspath(dirs)
name = abspath(name)
return name.startswith(join(the_dir, ''))
def getPort(url):
name = urlparse(url)[1]
parts = name.split(':')
return int(parts[-1])
class Node:
def __init__(self, url, dirname, secret):
self.url = url
self.dirname = dirname
self.secret = secret
self.known = set()
def query(self, query, history=[]):
try:
return self._handle(query)
except UnhandledQuery:
history = history + [self.url]
if len(history) >= MAX_HISTORY_LENGTH: raise
return self._broadcast(query, history)
def hello(self, other):
self.known.add(other)
return 0
def fetch(self, query, secret):
"""找到并下载资源"""
if secret != self.secret: raise AccessDenied
result = self.query(query)
f = open(join(self.dirname, query), 'wb')
f.write(result.data)
f.close()
return 0
def _start(self):
#启动XML_RPC服务器
s = SimpleXMLRPCServer(("", getPort(self.url)), logRequests=False)
s.register_instance(self)
s.serve_forever()
def _handle(self, query):
"""处理请求"""
name = join(self.dirname, query)
if not isfile(name): raise UnhandledQuery
if not inside(self.dirname, name): raise AccessDenied
return xmlrpclib.Binary(open(name, 'rb').read())
def _broadcast(self, query, history):
"""将查询广播到所有已知的Node"""
for other in self.known.copy():
if other in history: continue
try:
s = ServerProxy(other)
return s.query(query, history)
except Fault, f:
if f.faultCode == UNHANDLED: pass
else: self.known.remove(other)
except:
self.known.remove(other)
raise UnhandledQuery
def main():
url, directory, secret = sys.argv[1:]
n = Node(url, directory, secret)
n._start()
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt: sys.exit()
推荐阅读
热点文章
Discord.py(重写)on_member_update 无法正常工作
0
Discord.py 在 vc 中获取用户分钟数
0
discord.py 重写 |为我的命令出错
0
Discord.py rewrite 如何 DM 命令?
0
播放音频时,最后一部分被切断.如何解决这个问题?(discord.py)
0
在消息删除消息 Discord.py
0
如何使 discord.py 机器人私人/直接消息不是作者的人?
0
(Discord.py) 如何获取整个嵌入内容?
0
Discord bot 尽管获得了许可,但不能提及所有人
0
Discord.py discord.NotFound 异常
0
