1.目录结构
|__ config.ini
|__P2PClinet.py
|__P2PServer.py
|__url.txt
2.文件内容
config.ini
[SERVER_INFO] PORT = 服务器端口号 DIRECTORY = 共享文件夹的路径 URL_FILE = url.txt
P2PClinet.py
''' Created on 2012-7-21 author: Jeff_Yu ''' from xmlrpclib import ServerProxy, Fault from cmd import Cmd, PROMPT from random import choice from string import lower, lowercase from P2PServer import Node, UNHANDLED from threading import Thread from time import sleep import sys, ConfigParser, socket HEAD_START = 0.1 # seconds SECRET_LENGTH = 100 def randomString(length): """return the random string by given length""" chars = [] letters = lowercase[:26] while length > 0: length -= 1 chars.append(choice(letters)) return ''.join(chars) class Client(Cmd): prompt = '>' def __init__(self, url, dirname, urlfile): 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): 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 class MyConfigParser: def __init__(self, urlfile): self.urlfile = urlfile try: f = open(self.urlfile,"r") except IOError: meg = "file %s is not found in the path >> %s" % (self.urlfile,os.path.abspath('.')) return (0,meg) self.config = ConfigParser.ConfigParser() self.config.readfp(f) f.close() def getValueFromcfig(self,section,filed): try: value = self.config.get(section,filed) except ConfigParser.NoOptionError: meg = "%s is not found in file %s, under section %." %(filed, self.urlfile, section) return (0,meg) return(1,value) def main(): configfile = "config.ini" cfig = MyConfigParser(configfile) #get port res = cfig.getValueFromcfig("SERVER_INFO", 'PORT') if (res[0] == 0): print res[1] raw_input() sys.exit() else: port = res[1] #get directory res = cfig.getValueFromcfig("SERVER_INFO", 'DIRECTORY') if (res[0] == 0): print res[1] raw_input() sys.exit() else: directory = res[1] #get urlfile res = cfig.getValueFromcfig("SERVER_INFO", 'URL_FILE') if (res[0] == 0): print res[1] raw_input() sys.exit() else: urlfile = res[1] url = "http://%s:%s"%(socket.gethostname(),port) print "You URL is %s, you can introduce it to your friend."%url client = Client(url, directory, urlfile) client.cmdloop() if __name__ == '__main__': main()
P2PServer.py
''' Created on 2012-7-21 author: Jeff_Yu ''' from xmlrpclib import ServerProxy, Fault from os.path import join, isfile, abspath from SimpleXMLRPCServer import SimpleXMLRPCServer from urlparse import urlparse import sys SimpleXMLRPCServer.allow_reuse_address = 1 MAX_HISTORY_LENGTH = 6 UNHANDLED = 100 ACCESS_DENIED = 200 class UnhandledQuery(Fault): """ unable to handle the query """ def __init__(self, message = "Couldn't handle the query"): Fault.__init__(self, UNHANDLED, message) class AccessDenied(Fault): """ Access denied """ def __init__(self, message = "Access denied"): Fault.__init__(self, ACCESS_DENIED, message) def inside(dir, name): """ check whether can find file in the dir """ dir = abspath(dir) name = abspath(name) return name.startswith(join(dir,'')) def getPort(url): """get port from URL""" name = urlparse(url)[1] parts = name.split(':') return int(parts[-1]) class Node: """P2P network node""" def __init__(self, url, dirname, secret): self.url = url self.dirname = dirname self.secret = secret self.known = set() def query(self, query, history=[]): """ query the file""" try: return self._handle(query) except UnhandledQuery: history = history + [self.url] if len(history) >= MAX_HISTORY_LENGTH: raise return self._broadcast(query, history) def hello(self, other): """introduce self""" self.known.add(other) return 0 def fetch(self, query, secret): """make the node find file and download""" if secret != self.secret: raise AccessDenied result = self.query(query) f = open(join(self.dirname, query),'w') f.write(result) f.close() return 0 def _start(self): """start server""" s = SimpleXMLRPCServer(("", getPort(self.url)), logRequests=True, allow_none=True) s.register_instance(self) s.serve_forever() def _handle(self, query): dir = self.dirname name = join(dir, query) if not isfile(name): raise UnhandledQuery if not inside(dir, name): raise AccessDenied return open(name).read() def _broadcast(self, query, history): """used to query other known Node""" for other in self.known.copy(): if other in history:continue try: s = ServerProxy(other) return s.query(query, history) except Fault, f: if f.faultCode == UNHANDLED: pass else: self.known.remove(other) except: self.known.remove(other) raise UnhandledQuery def main(): url, directory, secret = sys.argv[1:] n = Node(url, directory, secret) n._start() if __name__ == '__main__': main()
url.txt
http://机器名称1:端口1 http://机器名称2:端口2 http://机器名称3:端口3
使用方法截图稍后发出。。。