5.再次实现
初次实现存在很多缺陷和缺点,这里不打算列出全部,而只列出几个重要的。
SimpleXMLRPCServer.allow_reuse_address = 1
如果你不想直接修改这个类,可创建其子类。其他几个问题解决起来要复杂些,将在接下来的几小节分别讨论。
5.1.创建客户端界面
客户端界面是使用模块cmd中的Cmd类实现的,有关其工作原理的详细信息,请参阅“Python库参考手册”。简单地说,你从Cmd派生出一个子类来创建一个命令行界面,同时对于要让它能够处理的每个命令(如foo),都创建一个方法(如do_foo)。这个方法将命令行余下的内容(一个字符串)作为其唯一的参数。例如,如果你在命令行界面输入以下内容:
say hello
将调用方法do_say,并将字符串'hello'作为其唯一的参数。Cmd的子类使用什么样的提示符取决于属性prompt。
这里的界面将只实现fetch(下载文件)和exit(退出程序)。命令fetch调用服务器的方法fetch,并在文件没有找到时打印一条错误信息。命令exit打印一个空行(这只是出于美观考虑)并调用sys.exit。(EOF表示已到达文件末尾。在UNIX系统中,用户按下Ctrl+D时将执行这个命令。)
然而,在构造函数中需要做什么呢?你希望每个客户端都与其对等体关联起来。为此,可创建一个Node对象并调用其方法_start,但如果这样做,客户端在方法_start返回前什么都做不了,这导致客户端毫无用处。为解决这个问题,可在一个独立的线程中启动Node。通常,使用线程时需要使用锁等机制做大量的防护和同步工作。然而,由于Client只通过XML-RPC与其Node交互,你无需做任何防护和同步工作,要在独立的线程中运行方法_start,只需将下面的代码放在程序的某个合适位置:
from threading import Thread
n = Node(url, dirname, self.secret)
t = Thread(target=n._start)
t.start()
警告 修改这个项目的代码务必小心。Client开始与Node对象直接交互(或相反)后,很容易出现与线程化相关的问题。修改代码前,务必完全理解线程化。
为确保你使用XML-RPC连接到它时已完全启动,先启动服务器,再使用teme.sleep等待一段时间。
然后,遍历一个包含url文件的所有行,并使用方法hello将服务器介绍给这些行表示的对等体。
你不用自己去设置密码,可使用自定义函数random_string,它生成一个由Client和Node共享的随机密码字符串。
5.2.引发异常
不返回表示成功还是失败的编码,而是假定肯定会成功,并在失败时引发异常。在XML-RPC中,异常(或故障)是使用数字标识的。在这个项目中,我随意的选择了100和200这两个数,分别用于表示正常的失败(请求未得到处理)和请求被拒绝(拒绝访问)。
异常是xmlrpc.client.Fault的子类。在服务器中引发的异常将传递到客户端,并保持faultCode不变。如果在服务器中引发了普通异常(如IOError),也将创建一个Fault类实例,因此你不能在服务器中随意使用异常。
5.3.验证文件名
需要处理的最后一个问题是,检查指定的文件是否包含在指定的目录中。这样做的方法有很多,但为独立于平台(即适用于Windows、UNIX和macOS),应使用模块os.path。
这里采用的简单方法如下:根据目录名和文件名创建绝对路径(例如,这将把'/foo/bar/../baz'转换为'/foo/baz'),将目录名与空文件名合并以确保它以文件分隔符(如'/')结尾,再检查绝对文件名是否以绝对路径打头。如果是这样的,就说明指定的文件包含在指定的目录中。
再次实现的完整源代码如图所示。
5.4.尝试使用
下面来看看如何使用这个程序。首先向下面这样启动它:
python client.py urls.txt directory http://localhost:4242
文件urls.txt里的每行应包含一个URL,即包含其他所有已知对等体的URL。通过第二个参数指定的目录应包含要共享的文件(新文件也将下载到这个目录)。最后一个参数是对等体的URL。运行这个命令时,将出现类似于下面的提示符:
>
下面来尝试获取一个不存在的文件:
通过(在同一台计算机的不同端口或不同计算机上)启动几个相互认识的节点(为确保这些节点相互认识,只要将它们的URL都放在URL文件即可),可尝试像使用第一个原型那样使用这个程序。玩烦了后,再接着阅读下一节。
6.进一步探索
对于这个系统,你可能会想出多种改进和扩展方式。下面是以下探索建议。
本文分享自 Python机器学习算法说书人 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!