1.问题

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

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

需求:

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

(2)向节点请求文件

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

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

(5)必须提供用户界面

2.准备工具

使用的主要模块是xmlrpclib,SimpleXMLPRCServer。共享界面可以使用标准库中的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:\program\pybook\27目录下创建两个文件夹files1和files2,在files2文件中放入test.txt文件,内容为"This is a test."。

打开两个cmd窗口,进入F:\program\pybook\27目录。

在第一个终端内运行: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:\program\pybook\27目录下建立两个文件夹,files1和files2,并在文件夹中分别建立urls1.txt和urls2.txt文件,files2文件夹里面创建一个文件,dict.txt。在urls1.txt中写入:http://localhost:4243,然后开启两个cmd命令行,

url, directory, urlfile

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

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

第27章 项目8:使用XML-RPC进行文件共享的更多相关文章

  1. 【ASP.NET MVC 5】第27章 Web API与单页应用程序

    注:<精通ASP.NET MVC 3框架>受到了出版社和广大读者的充分肯定,这让本人深感欣慰.目前该书的第4版不日即将出版,现在又已开始第5版的翻译,这里先贴出该书的最后一章译稿,仅供大家 ...

  2. 什么是XML RPC?

    # -*- coding: cp936 -*- #python 27 #xiaodeng #什么是XML RPC? #中文叫:远程过程调用 #使用http协议做传输协议的rpc机制,使用xml文本的方 ...

  3. 【STM32H7教程】第27章 STM32H7的TCM,SRAM等五块内存的动态内存分配实现

    完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第27章       STM32H7的TCM,SRAM等五块内 ...

  4. SpringMVC项目学习1_web.xml

    最近接触的所有项目都是SpringMVC+ajax的项目,因此以一个项目为例学习下. --------------------------------------------------------- ...

  5. Gradle 1.12用户指南翻译——第四十一章. 项目报告插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  6. 【RL-TCPnet网络教程】第27章 DNS域名系统基础知识

    第27章      DNS域名系统基础知识 本章节为大家讲解DNS(Domain Name System,域名系统),通过前面章节对TCP和UDP的学习,需要大家对DNS也有个基础的认识. (本章的知 ...

  7. JavaWeb项目中web.xml有关servlet的基本配置

    JavaWeb项目中web.xml有关servlet的基本配置: 我们注意到,tomcat下的conf中也有一个web.xml文件,没错的,所有的JavaWeb项目中web.xml都继承自服务器下的w ...

  8. [Real World Haskell翻译]第27章 网络通信和系统日志 Sockets and Syslog

    第27章 网络通信和系统日志 Sockets and Syslog 基础网络 在本书的前面几章,我们讨论了运转在网络上的服务.其中的两个例子是客户端/服务器架构的数据库和Web服务.当需要制定一个新的 ...

  9. The type javax.xml.rpc.ServiceException cannot be resolved.It is indirectly

    The type javax.xml.rpc.ServiceException cannot be resolved.It is indirectly 博客分类: 解决方案_Java   问题描述:T ...

随机推荐

  1. 一个Java线程死锁的例子

    package com.lk.B; public class Test4 { private static final Object o1 = new Object(); private static ...

  2. ARC 和 MRC 小结

    ARC 和 MRC 内存管理 从 MRC—>ARC 就是将内存管理部分,从开发者的函数中转移到函数外部的runtime 中.由于 runtime 的开发简单,逻辑层次高,所以 runtime 的 ...

  3. Stream Collector

    // Accumulate names into a List List<String> list = people.stream().map(Person::getName).colle ...

  4. Dapper使用方法:dapper-dot-net/Tests/Tests.cs解析(1)方法:TestMultiMapWithConstructor

    sql: SELECT * FROM users; SELECT * FROM posts; SELECT * FROM Posts p LEFT JOIN Users u ON u.Id= p.Ow ...

  5. 【谷歌市场安装】Google Play 闪退问题解决

    Google Play 安装后闪退,是因为手机没有内置GMS(Google Mobile Service) 框架. 由于谷歌退出了中国市场,国产手机很多都没有内置GMS, 导致Google Play ...

  6. Kinect For Windows V2开发日志五:使用OpenCV显示彩色图像及红外图像

    彩色图像 #include <iostream> #include <Kinect.h> #include <opencv2\highgui.hpp> using ...

  7. 怒刷DP之 HDU 1160

    FatMouse's Speed Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Su ...

  8. Application Loader上传app时报错:the bundle identifier cannot be changed from the current value

    报错如图: 解决:用info.plist中的bundle identifier生成发布证书(Distribution),如图:

  9. 导出用户列表到Excel的几种方法

    最近客户在咨询着怎么把SharePoint上面的用户列表给到出Excel,查看了一下,SharePoint并没有提供直接可用的导出功能(虽然都是List,但就是不让你导出...) 网上搜索了一下,方法 ...

  10. 【学习笔记】【C语言】关系运算符

    1. 条件判断 默认情况下,我们在程序中写的每一句正确代码都会被执行.但很多时候,我们想在某个条件成立的情况下才执行某一段代码 这种情况的话可以使用条件语句来完成,但是我们暂时不学习条件语句,先来看一 ...