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. 【Android Studio使用教程2】Android Studio创建项目

    创建项目 首先,先指出Android Studio中的两个概念. Project 和 Module .在Android Studio中, Project 的真实含义是工作空间, Module 为一个具 ...

  2. Event Handling in Spring

    Spring内置的event有 1.ContextRefreshedEvent This event is published when the ApplicationContext is eithe ...

  3. poj 1330 Nearest Common Ancestors 裸的LCA

    #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #i ...

  4. C#微信开发回复信息

    using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Web;usi ...

  5. [转载]JSON序列化与反序列化

    转载:http://www.cnblogs.com/ejiyuan/archive/2010/04/09/1708084.html 方法一:引入System.Web.Script.Serializat ...

  6. PAT1028—— 人口普查

    某城镇进行人口普查,得到了全体居民的生日.现请你写个程序,找出镇上最年长和最年轻的人. 这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过200岁的老人,而今天是2014年9月 ...

  7. 人情世故&潜规则

    大凡成功的牛人,无一例外都明白这一点.他们读懂了社会的本质和人际交往的潜规则,知道对方需要什么,知道对方脑子里在想什么.你几乎看不见他奔波劳碌,但是在不动声色中,他就已经实现人生目标.他们成功的密码是 ...

  8. asp.net C#生成和解析二维码代码

    类库文件我们在文件最后面下载 [ThoughtWorks.QRCode.dll 就是类库] 使用时需要增加: using ThoughtWorks.QRCode.Codec;using Thought ...

  9. Mysql中IFNULL与IN操作

    Mysql IFNULL操作 项目中用到的,当SQL查询某个字段为空的时候,查询结果中设置其值为默认值.最笨的方法当然是对查询结果进行处理了,遍历查询结果,当为空的时候,设置其值: 代码如下 复制代码 ...

  10. (转)Yale CAS + .net Client 实现 SSO(1)

    由于信息系统集成需要,最近研究了一下CAS.从网上找了不少资料,很多是针对Java平台的,为数不多的针对.net Client的文章往往片面的介绍某个方面,照着去做确会遇到大量的问题,特别是“重定向循 ...