Beginning Python Chapter 27

来源:互联网 发布:最美的句子知乎 编辑:程序博客网 时间:2024/05/16 01:21

First, I created the simple_node file, and as for I am using the Python 3.0, so there are several changes in the reference libs.

1. In 3.0, we use the xmlrpc lib and there are two module client and server under it. So normally, we should code as 'from xmlrpc import client' and from xmlrpc import server'.

2. In 3.0, the urlparse method has been included in the parse module under the urllib. Thus, we could use 'from urllib import parse' sentence.

3. For single underscore, it means it is a protected object and for double underscore, it means it is a private object which is more strict than single underscore when it is used.

4. After coding by using the cmd as the interface, you need to add the double quote mark when you refer to a folder name including blank, such as <client.py "D:/Python Program/Chapter27/file1/test.txt" "D:/Python Program/Chapter27/file1" http://localhost:4242

client_f.py

from xmlrpc import server, clientfrom xmlrpc.client import Faultfrom cmd import Cmdfrom random import choicefrom string import ascii_lowercasefrom server_f import Node, UNHANDLEDfrom threading import Threadfrom time import sleepimport sysHEAD_START = 0.1 #SecondsSECRET_LENGTH = 100def randomString(length):    """    返回给定长度的由字母组成的随机字符串。    """    chars = []    letters = ascii_lowercase[:26]    while length > 0:        length -= 1        chars.append(choice(letters))    return ''.join(chars)class Client(Cmd):    """    Node类的简单的基于文本的界面。    """    prompt = '>'    def __init__(self, url, dirname, urlfile):        """        设定url、dirname和urlfile,并且在单独的线程中启动Node服务器。        """        Cmd.__init__(self)        self.secret = randomString(SECRET_LENGTH)        n = Node(url, dirname, self.secret)        t = Thread(target=n._start)        t.setDaemon(1)        t.start()        #让服务器先启动        sleep(HEAD_START)        self.server = client.ServerProxy(url)        for line in open(urlfile):            line = line.strip()            self.server.hello(line)    def do_fetch(self, arg):        "调用服务器的fetch方法"        try:            self.server.fetch(arg, self.secret)        except Fault as f:            if f.faultCode != UNHANDLED: raise            print("Couldn't find the file", arg)    def do_exit(self, arg):        "退出程序"        print()        sys.exit()    do_EOF = do_exitdef main():    urlfile, directory, url = sys.argv[1:]    client = Client(url, directory, urlfile)    client.cmdloop()if __name__ == '__main__': main()


server_f.py

from xmlrpc import serverfrom os.path import join, isfile, abspathfrom urllib import parsefrom xmlrpc.server import Faultimport sysserver.SimpleXMLRPCServer.allow_reuse_address = 1MAX_HISTORY_LENGTH = 6UNHANDLED = 100ACCESS_DENIED = 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_DENIED, message)def inside(dir, name):    """    检查给定的目录中是否有给定的文件名。    """    dir = abspath(dir)    name = abspath(name)    return name.startswith(join(dir,''))def getPort(url):    '用URL提取端口'    name = parse.urlparse(url)[1]    parts = name.split(':')    return int(parts[-1])class Node:    """    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:            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):        """        内部使用,用于启动XMLRPC服务器。        """        s = server.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 = client.ServerProxy(other)                return s.query(query, history)            except Fault as f:                if f.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()


0 0
原创粉丝点击