项目八:使用XML-RPC进行文件共享

*首次实现的问题*
1.启动交互式Python解释器是mypeer.peer函数会报错
socket.error: [Errno 10061] 表示服务器忙碌中无法与您建立联机,请稍后再试。
(前面两个要在cmd下进入文件所在的目录)
2.sceret意义何在,query就将数据读取了,只不过没有以文件形式保存下了,这时以openfile把data写入文件,fetch不就没有意义了。
流程:query查询,返回code,判断是否拥有这个文件:有,fetch来判断密码,正确,写入文件,错误,返回code=2
代码
simple_node.py

# -*- coding:utf-8 -*-
from xmlrpclib import ServerProxy
from os.path import join, isfile
from SimpleXMLRPCServer import SimpleXMLRPCServer
from urlparse import urlparse
import sys

MAX_HiSTORY_Len = 6
ok = 1
FAIL = 2
EMPTY = ''

def getPort(url):
    name = urlparse(url)[1]
    parts = name.split(':')
    return int(parts[-1])

class Node(object):
    #P2P网络节点
    def __init__(self,url,dirname,secret):
        self.url = url
        self.dirname =dirname
        self.secret = secret
        self.known = set()

    def query(self,query,history=[]):
        code, data = self._handle(query)
        if code == ok:
            return code, data
        else:
            history  = history + [self.url]
            if len(history) >= MAX_HiSTORY_Len:
                return FAIL, EMPTY
            return self._broadcast(query,history)

    def hello(self,other):
        self.known.add(other)
        return ok

    def fetch(self,query,secret):
        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):
        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):
            return FAIL, EMPTY
        return OK , open(name).read()

    def _broadcast(self,query,history):
        for other in self.known.copy():
            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:]
    print url,dict,secret
    n = Node(url,directory, secret)
    n._start()

if __name__ == '__main_':
    main()

再次实现:
1.将于client.py ,url.txt放置在要共享的目录下
2.同时运行几个client.py,分配不同的端口

server:

# -*- coding:utf-8 -*-
from xmlrpclib import ServerProxy, Fault
from os.path import join, abspath, isfile
from SimpleXMLRPCServer import SimpleXMLRPCServer
from urlparse import urlparse
import sys

SimpleXMLRPCServer.allow_reuse_address = 1

MAX_HISTORY_LEN = 6
UNHANDLED = 100
ACCESS_DENIED  = 200

class UnhandledQuery(Fault):
    #表示无法处理的异常
    def __init__(self,message="couldn't handle the query"):
        Fault.__init__(self,UNHANDLED,message)

class AccessDenied(Fault):
    #在用户试图访问未被授权的资源引发的异常
    def __int__(self,message="Access denied"):
        Fault.__init__(self,ACCESS_DENIED,message)

def inside(dir,name):
    #检查dir中是否有给定的文件名
    dir = abspath(dir)
    name = abspath(name)
    return name.startswith(join(dir,''))

#从url中提取port,输入形式为http://...:port
def getPort(url):
    name = urlparse(url)[1]
    parts = name.split(':')
    return int(parts[-1])

class Node(object):
    #P2P网络节点
    def __init__(self,url,dirname,secret):
        self.url = url
        self.dirname =dirname
        self.secret = secret
        self.known = set()

    def query(self,query,history=[]):#查询文件,了能向其他已知节点请求帮助。将文件作为字符串返回
        try:
            code, data = self._handle(query)
        except UnhandledQuery:
            history  = history + [self.url]
            if len(history) >= MAX_HISTORY_LEN:
                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 ACCESS_DENIED
        result =self.query(query)
        f = open(join(self.dirname,query),'w')
        f.write(result)
        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):#内部使用,处理请求
        dir = self.dirname
        name = join(dir,query)
        if not isfile(name):
            raise UNHANDLED
        if not inside(dir,name):
            raise ACCESS_DENIED
        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,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:]
    print url,dict,secret
    n = Node(url,directory, secret)
    n._start()

if __name__ == '__main_':
    main()

client.py

# -*- coding:utf-8 -*-

from xmlrpclib import ServerProxy, Fault
from cmd import Cmd
from random import choice
from string import lowercase
from threading import Thread
from server import Node,UNHANDLED
from time import sleep
import sys

HEAD_START = 0.1 #seconds
SECRET_LEN = 100

def randomString(length):#返回给定长度的有字母组成的随机字母串
    chars = []
    letters = 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_LEN)
        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, f:
            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()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值