python项目8:xml-rpc共享文件

本文档介绍了P2P(对等网络)技术在文件共享程序中的应用,详细阐述了节点的属性和方法,包括查询、获取和存储文件、向其他节点自我介绍等功能。通过Python实现了一个简单的XML-RPC程序,展示了如何利用P2P技术进行文件查询和传播,同时防止循环请求。节点间通过密码认证确保安全性,并具备用户界面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

P2P
peer to peer:即对等体到对等体;在传统的程序中,常常采用服务器-客户端模式的架构,客户端向服务器发送请求,服务器响应请求返回;P2P技术不同,这是一种远程过程(函数调用),不同于CS结构,p2p中每个程序对等,任何对等体可以连接到其他对等体
文件共享程序的需求
1.每个节点必须跟踪一组已知的结点,以便向其寻求帮助;同时还必须让结点能够向其他节点介绍自己,从而成为其他节点跟踪集中的一个
2.节点必须通过提供的文件名向其他节点请求文件;如果对方有这样的文件,应将其返回;没有向其他邻居请求改文件,请求的节点如果有此文件就返回
3.为避免循环请求,过长的请求链;向节点查询必须提供历史记录
4.必须能够连接到其他的结点,并将自己标识为信任方(密码);通过这样,结点可以使用如下载、存储等限制功能
5.用户界面
节点的实现
节点的属性:
目录名:让结点知道从哪里去查找文件或将文件存储在那
密码:
一组已知的对等体(URL)
URL:加入到查询历史记录中
node的方法:
查询:查询文件是否存在query()
获取和存储文件:fetch()
向其他节点介绍自己:hello()
节点的实现:
hello():hello()只需添加节点就可以了
fetch():
调用query()接收结果,如果查到了内容,将其存储在本地文件,没有返回fail
query():负责查询并返回结果,由于需要知道是否查到了数据,因此增加一个code作为返回码,为1时有值,为2时无值;
query()进一步抽象,设置_handle()和_broadcast()内部方法实现:
    _handle()实现查询文件方法
    _broadcast():向其他节点查询

结构

simple_node.py

# --------------------------------------------------
# !/usr/bin/python
# -*- coding: utf-8 -*-
# PN: xml-rpc
# FN: simple_node
# Author: xiaxu
# DATA: 2022/4/22
# Description:初次实现简单的xml_rpc程序
# ---------------------------------------------------
from xmlrpc.client import ServerProxy
from xmlrpc.server import SimpleXMLRPCServer
from os.path import join,isfile
import sys
from urllib.parse import urlparse

OK = 1
Fail = 2
MAX_LENGTH = 6 #节点的最大长度为6
EMPTY = ''
def get_port(url):
    """
    获取端口号
    :param url:
    :return:
    """
    name = urlparse(url)[1] #获取ip:port
    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 hello(self,other):
        """
        添加节点的url
        :param other:
        :return:
        """
        self.known.add(other)
        return OK

    def query(self,query,history=[]):
        """
        查询文件是否存在,向其他添加的节点查询;返回数据
        :return:
        """
        code,data = self._query(query)
        if code ==OK:return code,data
        else:
            #如果没有查到就广播像其他节点查询
            #print('向其他节点查询')
            history = history+[self.url] #本url添加到查询记录
            if len(history)>=MAX_LENGTH:
                return Fail,EMPTY
            return self._broadcast(query,history)

    def fetch(self,query,secret):
        """
        调用查询,存储文件
        :return:
        """
        if secret != self.secret:return Fail
        code,data = self.query(query)
        if code == OK:
            #正常返回了数据,将数据文件写入本地
            f = open(join(self.dirname,query),'w') #
            f.write(data)
            f.close()
            return OK
        else:
            return Fail

    def _start(self):
        """
        启动方法
        :return:
        """
        s = SimpleXMLRPCServer(("",get_port(self.url)),logRequests=False)
        s.register_instance(self)
        s.serve_forever()

    def _query(self,query):
        """
        抽象的查询的方法
        :return:
        """
        dir = self.dirname
        name = join(dir,query)
        print("路径:",dir,name)
        if not isfile(name):return Fail,EMPTY  #Test whether a path is a regular file
        return OK,open(name).read()

    def _broadcast(self,query,history):
        """
        向其他节点广播并查询
        :return:
        """
        for other in self.known.copy():  #因为这里的known()可能会被remove(),因此copy()
            print("广播url:",other)
            if other in history:continue
            try:
                s = ServerProxy(other)
                code, data = s.query(query, history) #远程调用过程
                if code == OK:
                    return code, data
            except:
                self.known.remove(other)
        return Fail, EMPTY  #如果其他节点没有查到就返回空
def main():
    url, directory, secret = sys.argv[1:]
    n = Node(url, directory, secret)
    n._start()

if __name__ == '__main__':
    main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值