Python练习3-XML-RPC实现简单的P2P文件共享
来源:互联网 发布:网络人士周小平 编辑:程序博客网 时间:2024/06/02 05:38
XML-RPC实现简单的P2P文件共享
先来个百度百科:
XML-RPC的全称是XML Remote Procedure Call,即XML(标准通用标记语言下的一个子集)远程过程调用。它是一套允许运行在不同操作系统、不同环境的程序实现基于Internet过程调用的规范和一系列的实现。这种远程过程调用使用http作为传输协议,XML作为传送信息的编码格式。Xml-Rpc的定义尽可能的保持了简单,但同时能够传送、处理、返回复杂的数据结构。这个过程也被大家称为“分布式计算”。
学习资料地址:
https://docs.python.org/3/library/xmlrpc.html
https://www.the5fire.com/python-project8-xml-rpc.html
下面是测试例子:环境 Python 3.6 [版本小于3.x需改更改部分代码]
服务端
from xmlrpc.server import SimpleXMLRPCServers = SimpleXMLRPCServer(("",4242))def twice(x): return x*2s.register_function(twice) s.serve_forever()
客户端
import xmlrpc.clients = xmlrpc.client.ServerProxy('http://localhost:4242')print(s.twice(2))
执行结果
然后步入正题,写一个文件共享的例子(python 3.6):
例子很简单,详情看注释。
Server.py
from xmlrpc.server import SimpleXMLRPCServerfrom xmlrpc.client import ServerProxy,Faultfrom os.path import join,abspath ,isfileimport sysimport urllib SimpleXMLRPCServer.allow_reuse_address = 1MAX_HISTORY_LENGTH = 6 UNHANDLED = 100ACCESS_ENIED = 200 class UnhandledQuery(Fault): def __init__(self ,message="Couldn't handle the query"): Fault.__init__(self ,UNHANDLED ,message) class AccessDenied(Fault): def __init__(self,message="Access denied"): Fault.__init__(self ,ACCESS_ENIED ,message) def inside(dir ,name): dir = abspath(dir) name = abspath(name) return name.startswith(join(dir ,'')) def getPort(url): name = urllib.parse.urlparse(url)[1] patrs = name.split(':') return int(patrs[-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) ,'w') f.write(result) f.close() return 0 def _start(self): s = SimpleXMLRPCServer(("" ,getPort(self.url)),logRequests=False) s.register_instance(self) s.serve_forever() def _handle(self ,query): dir = self.dirname name = join(dir ,query) if not isfile(name) : raise UnhandledQuery if not inside(dir ,name): raise AccessDenied return open(name).read() def _broadcast(self ,query ,history): for other in self.known.copy(): if other in history : continue try: s = ServerProxy(other) return s.query(query ,history) except Fault: self.known.remove(other) #if Fault.faultCode == UNHANDLED: pass #else: self.known.remove(other) except: self.known.remove(other) raise UnhandledQuerydef main(): url,directory ,secret = sys.argv[1:] n = Node(url ,directory ,secret) n._start()if __name__ == '__main__' : main()
Client.py
from xmlrpc.client import ServerProxy,Faultfrom cmd import Cmdfrom random import choicefrom string import ascii_lowercasefrom server import Node,UNHANDLEDfrom threading import Threadfrom time import sleepimport sys HEAD_START = 0.1 # SecondsSECRET_LENFGTH = 100 def randomString(length): chars = [] letters = ascii_lowercase[:26] while length > 0: length -= 1 chars.append(choice(letters)) return ''.join(chars) class Client(Cmd): prompt = '> ' def __init__(self ,url ,dirname ,urlfile): Cmd.__init__(self) self.secret = randomString(SECRET_LENFGTH) n = Node(url ,dirname ,self.secret) t = Thread(target=n._start) t.setDaemon(1) t.start() sleep(HEAD_START) self.server = ServerProxy(url) for line in open(urlfile): line = line.strip() self.server.hello(line) def do_fetch(self ,arg): try: self.server.fetch(arg ,self.secret) except Fault: #if f.faultCode != UNHANDLED : raise print("Couldn't find the file"+arg) def do_exit(self ,arg): print sys.exit() do_EOF = do_exit def main(): urlfile,directory,url = sys.argv[1:] client = Client(url ,directory ,urlfile) client.cmdloop()if __name__ == '__main__' : main()
屡下上面代码工作流程,主要分为两部分,service和Client,service主要是维护一些节点信息,Client主要是用于当前用户发送请求和交互的地方。
入口是从Client开始,主函数进来接受几个参数:
(1)Urlfile.txt 路径,这个是一个文件,里面存着一些其他节点的链接url和端口,模拟当前节点用户的”伙伴”,如果把所有节点看成一张有向图的话,A->B A->c A->D 那么A节点里的这个utlfile里存的就是BCD的链接信息。当然这里是为了模拟,实际情况可能是在某个位置获取,或者是在运行过程中不断积累的。
(2)第二个参数directory路径,也就是指向一个路径,当做是当前节点的共享文件夹。
(3)最后一个url参数,是本地service的node节点建立服务的url和端口,比如要开一个本地端口2333的Node节点服务,直接传递http://localhost:2333。
得到参数之后,是先进入客户端client类,构造函数里面先随机生成一个本地密码,然后在创建一个Node节点,把Node节点的_start作为线程函数创建线程(_start是创建服务器节点并且开启监听),然后在创建一个ServerProxy链接自己机器上这个Node节点服务,调用服务的Hello函数把urlfile里面的伙伴信息都hello进去(hello是存的链接信息表)。至此Client的初始化完成。
Client初始化之后,就cmdloop了,相关连的韩式Client里面的两个函数do_fetch和exit。Fetch函数获取文件。客户端通过调用这个发送获取文件的命令。这里阿敏直接是请求本地Node节点的fetch函数,本地节点这个函数接到命令后是先判断下密码(其实觉得这个密码就是摆设),然后开始进入query函数来查询文件,query函数里面是先尝试一波看看文件在不在本地,如果不在的话就判断下是不是达到请求限制了,如果没到的话就把自己的朋友链拿出来,直接调广播告调用朋友们的query函数(RPC),朋友的query也是这个逻辑,本地有就直接返回结果,没有继续调用朋友的朋友。这个地方如果抽象成图的话就是深度优先搜索遍历(DFS),当然可以想办法BFS。这样最后调查结果会回溯到发起问题的起始节点,也就是最开始客户端调用的fetch函数,如果找到文件就保存起来,没找都就输出相关提示就行了。这个就是这个XMP-PRC(上面代码) 简单例子的实现思路。最后是测试路程。
测试步骤如下
首先需要建立两个文件夹,A和C,C文件夹里面创建一个文件,B.txt,在A和C所在文件夹中建立urlsA.txt和urlsC.txt文件。里面在urlsA.txt中写入:http://localhost:4243,然后开启两个命令行
打开一个cmd窗口A
python client.py urlsA.txt A http://localhost:4242
fetch B.txt
执行完这两条命令,应该是看到的文件无法找到
再次打开一个窗口B(第一个窗口不关)
python client.py urls C.txt C http://localhost:4243
fetch B.txt
执行完两条命令,没有任何输出,说明文件在这个地方是能找到的。
此时再次回头在第一个打开的窗口中查找B fetch B.txt 发现还是没有找到,讲道理此时应该可以的,因为第一个里面有第二个的通讯地址。
把上面两个node反过来启动就可以了,因为在A启动的时候,链接B,但是B不在,A以为B下线了,就把B从列表里移出去了。
反过来执行,会发现A可以成功吧文件下载到A文件夹下。
上面所有代码就是个测试例子,有很多细节没有处理,可以根据实际情况多改改。好好熟悉熟悉XML-RPC以及P2P的基本原理。
- Python练习3-XML-RPC实现简单的P2P文件共享
- 基于python rpc的简单文件共享
- python项目练习八:使用XML-RPC进行远程文件共享
- python项目练习八:使用XML-RPC进行远程文件共享
- python项目练习八:使用XML-RPC进行远程文件共享
- Python项目8:使用XML-RPC进行文件共享
- python 多线程 XML RPC的实现
- python多线程XML-RPC的实现
- linux 下 rpc python 实例之使用XML-RPC进行远程文件共享
- python使用SimpleXMLRPCServer实现简单的rpc
- P2P的简单实现
- 8. Python脚本学习实战笔记八 使用XML-RPC进行文件共享
- 简单的RPC实现
- 简单实现的RPC
- Python实现简单的udp打洞(P2P)
- python实现的简单点对点(p2p)聊天
- XML-RPC 的 Apache 实现
- XML-RPC的java实现
- Leetcode 44. Wildcard Matching
- React/React Native 的ES5 ES6写法对照表2
- python input 提示 no encoding declared
- 【poj1456 】supermarket
- idea添加jar包时启动tomcat项目时显示jar包找不到
- Python练习3-XML-RPC实现简单的P2P文件共享
- JMS
- autojump——一步到位
- windows下安装composer,纯手工,绝对有效
- JavaScript 面向对象之一 —— 对象(对象与JSON的区别)
- 文件描述符与文件指针
- Effective Java读书笔记十三(Java Tips.Day.13)
- use bindiff to diff patch
- Qt_log2000_事件的传递