python下载迅雷资源助手_python练习七—P2P下载
最近有些事儿比较忙,python的学习就断断续续,这个练习来得比预期的晚,不过还好,不管做什么,我都希望能认真对待,认真做好每一件事。
引入
这个练习原书中称作“使用XML-RPC进行文件共享”,题目是从使用的技术介绍的,做完这个练习之后我觉得最终其实实现的是一个迅雷的雏形——一个P2P下载器。当然了实际使用中的下载工具远远比这个要复杂,包括断点续传,断网重连等等。
那么我们学习的方法也就明确了,使用到了P2P的概念和XML-RPC的原理,那么就从这两个开始吧。
关于P2P
额,这里不进行官方的概念介绍,结合这个练习说明P2P的大体原理。使用P2P之后,我们查找一个共享资源的大体流程如下
#P2P协议的理解,弱化了server-client的概念,在网络中,每个节点都可能是server,也可能是client,暂且把发起请求的称为client,处理请求的称为server
1. client向服务器A发起寻找文件test的请求2. A现在自己的目录下面寻找是否有test3. 如果有则返回该文件给client,程序结束4. 如果A服务器没有,则A遍历在线节点列表5. 如果找到,返回给client,结束6. 如果没有,返回空
由上的过程看出网络中每个节点需要具备以下功能:
#每个节点需要维护的资源
共享目录:在网络中存在n台机器,每台服务器都有一个可供其他服务器访问的目录(目录下面有各种文件)
在线节点列表:每天机器都有一个所有愿意共项目录的服务器列表#服务器的功能
服务器应该能更新在线节点列表
如果在线节点很多,是不是应该一直寻找下去(设置一个查找深度)
服务器查询某个文件是否存在
服务器可以下载某一个文件到自己的共享目录
很明白了,在P2P网络中每个节点可以为别人提供资源,也可以向其他节点请求资源,对于每个节点来说就是共享出自己的资源,然后知道去哪里请求资源(需要一个其他节点的列表)。
关于xml-rpc
rpc:远程过程调用(之前学习分布式操作系统的时候想不到远程过程调用是什么,使用场景是什么,但是相信总起到了我意识到或者没意识到的作用),心爱那个心爱那个其实和http协议也有类似的地方,都是请求其他计算机的资源,并不关心在其他计算机上是怎么实现的。其原理也就是
#xml_rpc原理
在server A定义方法method
在client使用A的proxy调用method
当然了,rpc还有更详细的协议规范,但是这一层都被xml-rpc通过封装屏蔽了。这里也不作进一步探寻了。
具体实现
主要有两个模块,client和server,主要功能在server中实现,client只是对server调用进行了一些封装。
server.py
#!/usr/bin/env python#-*- coding=utf-8 -×-
from xmlrpclib importServerProxy, Faultfrom os.path importjoin, isfile, abspathfrom SimpleXMLRPCServer importSimpleXMLRPCServerfrom urlparse importurlparseimportsys
MAX_HISTORY_LENGTH= 6SimpleXMLRPCServer.allow_reuse_address= 1UNHANDLED= 100ACCESS_DENIED= 200
classUnhandledQuery(Fault):"""表示无法处理的查询异常"""
def __init__(self, message='Could not handle the query'):
Fault.__init__(self, UNHANDLED, message)classAccessDenied(Fault):"""在用户试图访问未被授权的资源时引发的异常"""
def __init__(self, message='Access denied'):
Fault.__init__(self, ACCESS_DENIED, message)definside(dir, name):"""判断访问的目录是否有限制访问的目录,限制非法目录访问,比如/var/www/../data"""dirs=abspath(dirs)
name=abspath(name)return name.startswith(join(dirs, ''))defgetPort(url):"""根据url获取端口号"""name= urlparse(url)[1]
parts= name.split(":")return int(parts[-1])classNode:"""P2P网络中的节点"""
def __init__(self, url, directory, secret):
self.url=url
self.directory=directory
self.secret=secret
self.know=set()def query(self, query, history=[]):"""查找文件,先在本机查找,如果找到则返回,找不到则查找其他已知节点"""
try:print 'search local'
returnself._handle(query)exceptUnhandledQuery:#添加到history,标记查找的深度
history = history +[self.url]if len(history) >=MAX_HISTORY_LENGTH:raise
print 'search other server'
returnself._broadcast(query, history)defhello(self, other):"""认识其他节点"""self.know.add(other)return0deffetch(self, query, secret):"""用于从节点下载数据"""
print 'server.fetch'
if secret !=self.secret:raiseAccessDenied
result=self.query(query)print 'result----',result#把查询到的数据写到本地
f = open(join(self.directory, query), 'w')
f.write(result)
f.close()return0def_start(self):"""内部使用,用于启动XML_RPC服务器"""server= SimpleXMLRPCServer(("", getPort(self.url)), logRequests=False)
server.register_instance(self)
server.serve_forever()def_handle(self, query):"""搜索文件在本服务器上是否存在"""dirs=self.directory
name=join(dirs, query)if notisfile(name):raiseUnhandledQueryreturnopen(name).read()def_broadcast(self, query, history):"""内部时使用,用于将查询广播到其他已知节点"""
for other inself.know.copy():try:#根据url创建远程节点的proxy,使用xml_rpc进行远程调用
print 'search ----', other
server=ServerProxy(other)print 'start query', otherreturnserver.query(query, history)exceptFault, f:if f.faultCode ==UNHANDLED:pass
else:
self.know.remove(other)except:#说明该server已经不可用
self.know.remove(other)#如果在所有节点中没有找到,就返回空
raiseUnhandledQuerydefmain():
url, directory, secret= sys.argv[1:]
node=Node(url, directory, secret)
node._start()if __name__ == '__main__':
main()
server.py
client.py
#! /usr/bin/env python#-*- coding=utf-8 -*-
from xmlrpclib importServerProxy, Faultfrom cmd importCmdfrom random importchoicefrom string importlowercasefrom server importNode, UNHANDLEDfrom threading importThreadfrom time importsleepimportsys
HEAD_START= 0.1 #second
SECRET_LEN = 100
defrandomStr(len):"""生成指定长度的字符串"""chars=[]
letters= lowercase[:26]while len >0:
len= len - 1chars.append(choice(letters))return ''.join(chars)classClient1(Cmd):"""Node基于文本的界面"""
def __init__(self, url, dirname, urlfile):"""初始化Cmd
随机生成秘钥
启动服务器
启动字符界面"""
print 'in'Cmd.__init__(self)
self.secret=randomStr(SECRET_LEN)
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 inopen(urlfile):
line=line.strip()
self.server.hello(line)defdo_fetch(self, arg):"调用服务器的fetch方法"
try:print 'do_fetch'self.server.fetch(arg, self.secret)exceptFault, f:printfif f.faultCode !=UNHANDLED:raise
print 'Could not find the file', argdefdo_exit(self, arg):"退出程序"
printsys.exit()
do_EOF= do_exit #接收到EOF的时候也退出程序
#设置提示符
prompt = '>'
defmain():
urlfile, directory, url= sys.argv[1:]printurlfile, directory, urlprint '---------'
printdir()
client=Client1(url, directory, urlfile)
client.cmdloop()if __name__ == '__main__':
main()
client.py
总结
在运行这个练习的时候,要注意死锁,因为有共享资源的问题
#线程死锁
server A的url list里面有Server B
server B的url list里面有Server A
当A请求B的时候,B发现自己也没有,B根据url list查询其他server,这个时候根据list需要去查询A
但是这个时候A正在等待B的回应,所以就造成了
A等B,B等A的死锁情况#解决死锁
每个server B在向url list里面的server A发出请求之前判断本神是否是Server A正在请求B
完整代码
python下载迅雷资源助手_python练习七—P2P下载相关推荐
- python下载迅雷资源助手_python:you-get下载B站、优酷网站的在线视频
you-get 的使用方法是这样的,在命令行中输入 you-get https://www.bilibili.com/video/av8786599/ 可以看到 you-get的优点在于: 1.使用方 ...
- linux 命令界面 下载,[转载]命令行也强大之下载迅雷资源的方法
[转载]命令行也强大之下载迅雷资源的方法 发布时间:2010-02-27 19:27:43来源:红联作者:yaodechang www.diybl.com 时间:2009-05-02 作者:匿名 编辑 ...
- python编程狮苹果系统_Python编程狮app下载-Python编程狮苹果版v1.0
Python编程语言现在越来越流行了,在编程语言中的地位也越来越重要了,今天小编就把推荐给大家这个软件可以帮助大家去很好的学习Python编程语言,这个软件轻松的将用户领进们,让大家可以体验到Pyth ...
- python最好用的助手_python 好用
1秒创建局域网下载服务器 python有"内置电池"的称号, 安装Python3后, 你可以无需编码, 直接通过命令行使用python3部分"内置电池"的功能, ...
- python程序员专用壁纸_Python开发专属壁纸下载与轮换程序
本人对于壁纸一直偏佛系,不爱特意去找一堆壁纸.因此用Python简单地搞了一个自动下载壁纸,定时随机轮换的功能来自娱自乐,顺便分享给大家. 原文链接:https://www.codernice.top ...
- python编写下载器可暂停_python多进程断点续传分片下载器
python多进程断点续传分片下载器 标签:python 下载器 多进程 因为爬虫要用到下载器,但是直接用urllib下载很慢,所以找了很久终于找到一个让我欣喜的下载器.他能够断点续传分片下载,极大提 ...
- linux mint 下载迅雷安装包,linux mint 最新版本下载地址
Linux Mint是一种基于Ubuntu/Debian的Linux操作系统,于2006年开始发行,宗旨是提供一个免费开源.现代.优雅.功能强大易于使用的操作系统!Linux Mint有许多种不同的版 ...
- python下载迅雷资源_python将下载地址转换成迅雷跟qq旋风的下载地址
python将下载地址转换成迅雷和qq旋风的下载地址 迅雷和qq旋风下载,有加速和离线功能,很方面,我是在网上看到的原始地址和迅雷地址,qq旋风地址的转化原理,然后用python+pyqt写了一个客户 ...
- python下载迅雷资源_PYTHON实现迅雷、FLASHGET、QQ旋风转真实链接、磁链转种子文件、迅雷快传链接抓取 | 学步园...
# -*- coding: utf-8 -*- import re; import urllib2; import os; import base64; def get_kuaichuan_url(s ...
最新文章
- MECAT:PC组装人的基因组
- 镜像浏览器_Docker 企业级私有镜像仓库 Harbor 部署
- 回归架构本真:从规划、思维到设计,构建坚不可摧的架构根基
- String的concat方法与join方法
- Mozilla官方:Firefox 3.5.1问题并非安全漏洞 仅是堆溢出Crash
- 微服务之 EShop on dapr概览
- RotateDrawable
- 二叉树——二叉树问题(洛谷 P3884)
- 【Axure电商原型】电商app高保真原型、移动端通用版电商app模板、用户中心、会员体系、签到、高保真商城app、rp原型、直播、运营活动、订单管理、售后退款、电商系统、购物车、高保真移动端电商
- 计算机考试策略,计算机等级考试应试的策略.doc
- java的运行环境是什么_Java运行环境是什么
- 基于IE的MIME sniffing功能的跨站点脚本攻击
- 慕课网-安卓攻城狮视频学习及练习(六)
- 笨鸟的平凡之路-KETTLE的安装
- 服务器时装不显示不出来,常见问题FAQ汇总
- 3d max 场景转换对话框
- 高新技术企业申请,申请高新技术企业需要什么材料
- C#学习记录——软件工程师必备素养与技能
- 软件测试从业者必备核心素质
- 开博第一篇,申请博客的理由
热门文章
- 纽约Airbnb房源数据挖掘与房价预测评估模型
- 旅游网站首页——html
- 数理统计基础-相关系数
- 三菱FX系列PLC面板布置和PLC系统构成
- 谁先倒(15 分) 划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和,谁就输了,输家罚一杯酒
- NEO4J-相似度算法04-欧几里得距离算法(euclidean)应用场景简介
- win10代理服务器没有响应解决方案
- A or B Equals C Gym - 101028C
- 高通8996启动流程-2.总体启动流程
- 口红会染唇是什么意思_最强科普!口红、唇膏、唇釉、染唇液究竟区别在哪?...