Python 使用XML-RPC进行文件共享
1.目录结构
|__ config.ini
|__P2PClinet.py
|__P2PServer.py
|__url.txt
2.文件内容
config.ini
1
[SERVER_INFO]
2
PORT = 服务器端口号
3
DIRECTORY = 共享文件夹的路径
4
URL_FILE = url.txt
P2PClinet.py
001
'''
002
Created on 2012-7-21
003
004
author: Jeff_Yu
005
'''
006
007
from xmlrpclib import ServerProxy, Fault
008
from cmd import Cmd, PROMPT
009
from random import choice
010
from string import lower, lowercase
011
from P2PServer import Node, UNHANDLED
012
from threading import Thread
013
from time import sleep
014
import sys, ConfigParser, socket
015
016
HEAD_START = 0.1 # seconds
017
SECRET_LENGTH = 100
018
019
020
def randomString(length):
021
"""return the random string by given length"""
022
023
chars = []
024
letters = lowercase[:26]
025
while length > 0:
026
length -= 1
027
chars.append(choice(letters))
028
029
return ''.join(chars)
030
031
class Client(Cmd):
032
033
prompt = '>'
034
035
def __init__(self, url, dirname, urlfile):
036
037
Cmd.__init__(self)
038
self.secret = randomString(SECRET_LENGTH)
039
n = Node(url, dirname, self.secret)
040
t = Thread(target=n._start)
041
t.setDaemon(1)
042
t.start()
043
sleep(HEAD_START)
044
self.server = ServerProxy(url)
045
for line in open(urlfile):
046
line = line.strip()
047
self.server.hello(line)
048
049
050
def do_fetch(self, arg):
051
052
try:
053
self.server.fetch(arg, self.secret)
054
except Fault, f:
055
if f.faultCode != UNHANDLED: raise
056
print "Couldn't find the file", arg
057
058
def do_exit(self,arg):
059
060
print
061
sys.exit()
062
063
do_EOF = do_exit
064
065
class MyConfigParser:
066
067
def __init__(self, urlfile):
068
069
self.urlfile = urlfile
070
071
try:
072
f = open(self.urlfile,"r")
073
except IOError:
074
meg = "file %s is not found in the path >> %s" % (self.urlfile,os.path.abspath('.'))
075
return (0,meg)
076
077
self.config = ConfigParser.ConfigParser()
078
self.config.readfp(f)
079
080
f.close()
081
082
083
def getValueFromcfig(self,section,filed):
084
085
try:
086
value = self.config.get(section,filed)
087
except ConfigParser.NoOptionError:
088
meg = "%s is not found in file %s, under section %." %(filed, self.urlfile, section)
089
return (0,meg)
090
091
return(1,value)
092
093
094
095
def main():
096
097
configfile = "config.ini"
098
cfig = MyConfigParser(configfile)
099
100
#get port
101
res = cfig.getValueFromcfig("SERVER_INFO", 'PORT')
102
if (res[0] == 0):
103
print res[1]
104
raw_input()
105
sys.exit()
106
else:
107
port = res[1]
108
109
#get directory
110
res = cfig.getValueFromcfig("SERVER_INFO", 'DIRECTORY')
111
if (res[0] == 0):
112
print res[1]
113
raw_input()
114
sys.exit()
115
else:
116
directory = res[1]
117
118
#get urlfile
119
res = cfig.getValueFromcfig("SERVER_INFO", 'URL_FILE')
120
if (res[0] == 0):
121
print res[1]
122
raw_input()
123
sys.exit()
124
else:
125
urlfile = res[1]
126
127
url = "http://%s:%s"%(socket.gethostname(),port)
128
129
print "You URL is %s, you can introduce it to your friend."%url
130
131
client = Client(url, directory, urlfile)
132
client.cmdloop()
133
134
if __name__ == '__main__': main()
P2PServer.py
001
'''
002
Created on 2012-7-21
003
004
author: Jeff_Yu
005
'''
006
007
from xmlrpclib import ServerProxy, Fault
008
from os.path import join, isfile, abspath
009
from SimpleXMLRPCServer import SimpleXMLRPCServer
010
from urlparse import urlparse
011
import sys
012
013
014
SimpleXMLRPCServer.allow_reuse_address = 1
015
016
MAX_HISTORY_LENGTH = 6
017
018
UNHANDLED = 100
019
ACCESS_DENIED = 200
020
021
class UnhandledQuery(Fault):
022
"""
023
unable to handle the query
024
"""
025
026
def __init__(self, message = "Couldn't handle the query"):
027
Fault.__init__(self, UNHANDLED, message)
028
029
030
class AccessDenied(Fault):
031
"""
032
Access denied
033
"""
034
def __init__(self, message = "Access denied"):
035
Fault.__init__(self, ACCESS_DENIED, message)
036
037
038
def inside(dir, name):
039
"""
040
check whether can find file in the dir
041
"""
042
dir = abspath(dir)
043
name = abspath(name)
044
return name.startswith(join(dir,''))
045
046
047
def getPort(url):
048
"""get port from URL"""
049
050
name = urlparse(url)[1]
051
parts = name.split(':')
052
return int(parts[-1])
053
054
055
class Node:
056
"""P2P network node"""
057
058
def __init__(self, url, dirname, secret):
059
self.url = url
060
self.dirname = dirname
061
self.secret = secret
062
self.known = set()
063
064
def query(self, query, history=[]):
065
""" query the file"""
066
067
try:
068
return self._handle(query)
069
except UnhandledQuery:
070
history = history + [self.url]
071
if len(history) >= MAX_HISTORY_LENGTH: raise
072
return self._broadcast(query, history)
073
074
def hello(self, other):
075
"""introduce self"""
076
077
self.known.add(other)
078
return 0
079
080
def fetch(self, query, secret):
081
"""make the node find file and download"""
082
083
if secret != self.secret: raise AccessDenied
084
result = self.query(query)
085
f = open(join(self.dirname, query),'w')
086
f.write(result)
087
f.close()
088
return 0
089
090
091
def _start(self):
092
"""start server"""
093
094
s = SimpleXMLRPCServer(("", getPort(self.url)), logRequests=True, allow_none=True)
095
s.register_instance(self)
096
s.serve_forever()
097
098
def _handle(self, query):
099
100
dir = self.dirname
101
name = join(dir, query)
102
if not isfile(name): raise UnhandledQuery
103
if not inside(dir, name): raise AccessDenied
104
return open(name).read()
105
106
def _broadcast(self, query, history):
107
"""used to query other known Node"""
108
109
for other in self.known.copy():
110
if other in history:continue
111
112
try:
113
s = ServerProxy(other)
114
return s.query(query, history)
115
116
except Fault, f:
117
if f.faultCode == UNHANDLED: pass
118
else: self.known.remove(other)
119
except:
120
self.known.remove(other)
121
122
raise UnhandledQuery
123
124
def main():
125
url, directory, secret = sys.argv[1:]
126
n = Node(url, directory, secret)
127
n._start()
128
www.2cto.com
129
if __name__ == '__main__': main()
url.txt
1
http://机器名称1:端口1
2
http://机器名称2:端口2
3
http://机器名称3:端口3
作者:JeffYu