日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

Python练习3-XML-RPC实现简单的P2P文件共享

發布時間:2025/6/17 asp.net 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python练习3-XML-RPC实现简单的P2P文件共享 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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 SimpleXMLRPCServer s = SimpleXMLRPCServer(("",4242)) def twice(x):return x*2 s.register_function(twice) s.serve_forever()

客戶端

import xmlrpc.client s = xmlrpc.client.ServerProxy('http://localhost:4242') print(s.twice(2))
執行結果

?

然后步入正題,寫一個文件共享的例子(python?3.6):

例子很簡單,詳情看注釋。

?

Server.py

from xmlrpc.server import SimpleXMLRPCServer from xmlrpc.client import ServerProxy,Fault from os.path import join,abspath ,isfile import sys import urllibSimpleXMLRPCServer.allow_reuse_address = 1 MAX_HISTORY_LENGTH = 6UNHANDLED = 100 ACCESS_ENIED = 200class 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 = urlself.dirname = dirnameself.secret = secretself.known = set()def query(self ,query ,history=[]):try:return self._handle(query)except UnhandledQuery:history = history + [self.url]if len(history) >= MAX_HISTORY_LENGTH:raisereturn self._broadcast(query ,history)def hello(self ,other):self.known.add(other)return 0def fetch(self ,query ,secret):if secret != self.secret: raise AccessDeniedresult = self.query(query)f = open(join(self.dirname,query) ,'w')f.write(result)f.close()return 0def _start(self):s = SimpleXMLRPCServer(("" ,getPort(self.url)),logRequests=False)s.register_instance(self)s.serve_forever()def _handle(self ,query):dir = self.dirnamename = join(dir ,query)if not isfile(name) : raise UnhandledQueryif not inside(dir ,name): raise AccessDeniedreturn open(name).read()def _broadcast(self ,query ,history):for other in self.known.copy():if other in history : continuetry: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 UnhandledQuery def 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,Fault from cmd import Cmd from random import choice from string import ascii_lowercase from server import Node,UNHANDLED from threading import Thread from time import sleep import sysHEAD_START = 0.1 # Seconds SECRET_LENFGTH = 100def randomString(length):chars = []letters = ascii_lowercase[:26]while length > 0:length -= 1chars.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 : raiseprint("Couldn't find the file"+arg)def do_exit(self ,arg):printsys.exit()do_EOF = do_exitdef 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文件共享的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。