zoukankan      html  css  js  c++  java
  • 第27章 项目8:使用XML-RPC进行文件共享

    1.问题

    创建一个简单的P2P文件共享程序。

    P2P文件共享程序是在不同计算机上的程序交换文件。P2P交互内,任何节点(peer)都可以是链接到其他节点。在这样一个由节点组成的虚拟网络中,是没有中央节点的,这样网络会更强壮。P2P系统构建会有很多问题,但是大多数P2P系统都有聪明的方法来组织自己的结构。

    需求:

    (1)节点介绍自己给其他节点

    (2)向节点请求文件

    (3)为避免循环以及长距离请求,需要提供请求历史记录

    (4)程序必须有连接到节点并且将自己表示为可信任参与者的方法

    (5)必须提供用户界面

    2.准备工具

    使用的主要模块是xmlrpclibSimpleXMLPRCServer。共享界面可以使用标准库中的cmd模块,以获得一些非常有限的并行效果。此外还有threading模块,urlparse模块。输入以下命令检查模块:

    import xmlrpclib

    from SimpleXMLRPCServer import SimpleXMLRPCServer

    import threading

    import urlparse

    3.初次实现

    启动两个交互式的Python解释器,第一个解释器内顺序输入:

    from SimpleXMLRPCServer import SimpleXMLRPCServer

    s = SimpleXMLRPCServer(("",4242))

    def twice(x):

    return x*2

    s.register_function(twice)

    s.serve_forever()

    此时解释器被"挂起",等待RPC请求。为了创建请求,第二个解释器内输入:

    from xmlrpclib import ServerProxy

    s = ServerProxy('http://localhost:4242')

    s.twice(2)

    第二个解释器输出:4

    第一个解释器输出:

    127.0.0.1 - - [19/Nov/2016 13:48:02] "POST /RPC2 HTTP/1.1" 200 -

    程序需求最重要的两个方面包括:Node要维护什么信息,必须执行什么操作。

    27-1 simple_node.py ——简单的Node实现

    F:programpybook27目录下创建两个文件夹files1files2,在files2文件中放入test.txt文件,内容为"This is a test."。

    打开两个cmd窗口,进入F:programpybook27目录。

    在第一个终端内运行:python simple_node.py http://localhost:4242 files1 secret1

    在第二个终端内运行:python simple_node.py http://localhost:4243 files2 secret2

    打开交互式Python解释器,输入如下代码,运行第一个节点:

    from xmlrpclib import *

    mypeer = ServerProxy('http://localhost:4242')

    code, data = mypeer.query('test.txt')

    code

    输出:2

    代码2表示获取失败。

    运行第二个节点,代码如下:

    otherpeer = ServerProxy('http://localhost:4243')

    code, data = otherpeer.query('test.txt')

    code

    输出:1

    输入:data

    输出:'This is a test.'

    把第一个节点介绍给第二个节点:mypeer.hello('http://localhost:4243')

    输出:1

    然后获取,就可以从第二个节点上得到test.txt文件:mypeer.query('test.txt')

    输出:[1, 'This is a test.']

    把第二个节点的文件下载到第一个节点上:mypeer.fetch('test.txt','secret1')

    输出:1

    返回值1表示成功了,在files1文件夹中查看,存在test.txt文件。

    完整代码如下:

    >>> from xmlrpclib import *

    >>> mypeer = ServerProxy('http://localhost:4242')

    >>> code, data = mypeer.query('test.txt')

    >>> code

    2

    >>> otherpeer = ServerProxy('http://localhost:4243')

    >>> code, data = otherpeer.query('test.txt')

    >>> code

    1

    >>> data

    'This is a test.'

    >>> mypeer.hello('http://localhost:4243')

    1

    >>> mypeer.query('test.txt')

    [1, 'This is a test.']

    >>> mypeer.fetch('test.txt','secret1')

    1

    4.再次实现——该部分未能实现

    27-2 server.py ——新的Node实现

    # coding=utf-8
    from xmlrpclib import ServerProxy, Fault
    from cmd import Cmd
    from random import choice
    from string import lowercase
    from server import Node, UNHANDLED # 引入前面的server
    from threading import Thread
    from time import sleep
    import sys

    HEAD_START = 0.1 #Seconds
    SECRET_LENGTH = 100

    def randomString(length):
    """
    返回给定长度的由字母组成的随机字符串。
    """
    chars = []
    letters = 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,并且在单独的线程中启动No的服务器。
    """
    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 = 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, 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 #EOF与'exit'同义

    def main():
    url, directory, urlfile = sys.argv[1:]
    print url, directory, urlfile
    client = Client(url, directory, urlfile)
    client.cmdloop()

    if __name__ == '__main__': main()

    27-3 client.py ——新的Node控制器界面

    # coding=utf-8
    from xmlrpclib import ServerProxy, Fault
    from cmd import Cmd
    from random import choice
    from string import lowercase
    from server import Node, UNHANDLED # 引入前面的server
    from threading import Thread
    from time import sleep
    import sys

    HEAD_START = 0.1 #Seconds
    SECRET_LENGTH = 100

    def randomString(length):
    """
    返回给定长度的由字母组成的随机字符串。
    """
    chars = []
    letters = 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,并且在单独的线程中启动No的服务器。
    """
    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 = 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, 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 #EOF与'exit'同义

    def main():
    url, directory, urlfile = sys.argv[1:]
    print url, directory, urlfile
    client = Client(url, directory, urlfile)
    client.cmdloop()

    if __name__ == '__main__': main()

    F:programpybook27目录下建立两个文件夹,files1files2,并在文件夹中分别建立urls1.txturls2.txt文件,files2文件夹里面创建一个文件,dict.txt。在urls1.txt中写入:http://localhost:4243,然后开启两个cmd命令行,

    url, directory, urlfile

    第一个输入:python client.py urls1.txt files1 http://localhost:4242 并回车

    但是,很遗憾尝试多次依然报错,尚未解决。

  • 相关阅读:
    smarty对网页性能的影响
    php-fpm正在生成页面时,浏览器刷新后,php-fpm会退出吗?
    为什么日志记录到别的目录了?
    一个空格引发的bug
    linux内核--页高速缓存
    radix树
    linux内核--用户态内存管理
    linux内核--内核内存管理
    linux内核--软中断与tasklet
    linux内核--几个上下文(context)
  • 原文地址:https://www.cnblogs.com/Sumomo0516/p/6131746.html
Copyright © 2011-2022 走看看