传说中只用了十五行Python语句的P2P客户端/服务端 [转]
#zz from http://www.exonsoft.com/~kochin/TinyP2P/tinyp2p.html# tinyp2p.py 1.0 (documentation at http://freedom-to-tinker.com/tinyp2p.html)# (C) 2004, E.W. Felten# license: http://creativecommons.org/licenses/by-nc-sa/2.0# Annotated by Kochin Chang, Jan. 2005# Usage:# Server - python tinyp2p.py password server hostnameportnum # Client - python tinyp2p.py password client serverurl pattern# ar ar arar ar arimport sys, os, SimpleXMLRPCServer, xmlrpclib, re, hmac # Import libraries used in the program.# sys : system variables and functions.# os : portable OS dependent functionalities.# SimpleXMLRPCServer : basic XML-RPC server framework.# xmlrpclib : XML-RPC client support.# re : regular expression support.# hmac : RFC 2104 Keyed-Hashing Message Authentication.ar,pw,res = (sys.argv,lambda u:hmac.new(sys.argv,u).hexdigest(),re.search)# A multiple assignment.# ar <- sys.argv : the argument list.# pw <- lambda u:hmac.new(sys.argv,u).hexdigest() :# a function makes an HMAC digest from a URL.# INPUT: a string, u, which is a URL here.# OUTPUT: a hexdecimal HMAC digest.# DESCRIPTION:# 1. Creates a HMAC object from the URL using network's password,# sys.argv, as the key.# 2. Returns a hexdecimal digest of the HMAC object.# res <- re.search : alias for the regular expression search function.pxy,xs = (xmlrpclib.ServerProxy,SimpleXMLRPCServer.SimpleXMLRPCServer)# A multiple assignment.# pxy <- xmlrpclib.ServerProxy : alias for the ServerProxy class.# xs <- SimpleXMLRPCServer.SimpleXMLRPCServer : alias for the SimpleXMLRPCServer class.def ls(p=""):return filter(lambda n:(p=="")or res(p,n),os.listdir(os.getcwd()))# a function lists directory entries.# INPUT: a string, p, which is a regular expression pattern.# OUTPUT: a list of directory entries matched the pattern.# DESCRIPTION:# 1. Creates a function using lambda expression that takes a pathname as its# parameter. The function returns true if the pattern is empty or the# pathname matches the pattern.# 2. Finds out what is the current working directory.# 3. Retrieves a list of directory entries of current working directory.# 4. Filters the list using the lambda function defined.if ar!="client":# Running in server mode... myU,prs,srv = ("http://"+ar+":"+ar, ar,lambda x:x.serve_forever())# A multiple assignment.# myU <- "http://"+ar+":"+ar : server's own URL.# prs <- ar : URL's of other servers in the network.# srv <- lambda x:x.serve_forever() :# a function to start a SimpleXMLRPCServer.# INPUT: a SimpleXMLRPCServer object, x.# OUTPUT: (none)# DESCRIPTION:# Calls the server's serve_forever() method to start handling request. def pr(x=[]): return ([(y in prs) or prs.append(y) for y in x] or 1) and prs# a function returns the server list.# INPUT: a list, x, of servers' URLs to be added to the server list.# OUTPUT: the updated server list.# DESCRIPTION:# 1. For each URL in x, checks whether it's already in the server list.# If it's not in the list, appends in onto the list.# 2. Returns the updated server list. def c(n): return ((lambda f: (f.read(), f.close()))(file(n)))# a function returns content of the specified file.# INPUT: a string, n, which is a filename.# OUTPUT: the content of the file in a string.# DESCRIPTION:# 1. Creates a function using lambda expression that takes a file object, f,# as its parameter. The function reads the content of the file, then# closes it. The results of the read and close are put into a tuple, and# the tuple is returned.# 2. Creates a file object with the filename. Passes it to the lambda# function.# 3. Retrieves and returns the first item returned from the lambda function. f=lambda p,n,a:(p==pw(myU))and(((n==0)and pr(a))or((n==1)and )or c(a))# a request handling function, depending on the mode, returns server list,# directory entries, or content of a file.# INPUT: a string, p, which is a hexdecimal HMAC digest.# a mode number, n.# if n is 0, a is a list of servers to be added to server list.# if n is 1, a is a pattern string.# if n is anything else, a is a filename.# OUTPUT: if n is 0, returns the server list.# if n is 1, returns directory entries match the pattern.# if n is anything else, returns content of the file.# DESCRIPTION:# 1. Verifies the password by comparing the HMAC digest received and the# one created itself. Continues only when they match.# 2. If n is 0, calls pr() to add list, a, and returns the result.# If n is 1, calls ls() to list entries match pattern a, and returns# the result enclosed in a list.# If n is any other value, retreives and return content of the file# with filename specified in a. def aug(u): return ((u==myU) and pr()) or pr(pxy(u).f(pw(u),0,pr()))# a function augments the network.# INPUT: a string, u, which is a URL.# OUTPUT: a list of URL's of servers in the network.# DESCRIPTION:# 1. If the URL, u, equals to my own URL, just returns the server list.# 2. Otherwise, creates a ServerProxy object for server u. Then calls its# request handling function f with a HMAC digest, mode 0, and server# list with myself added.# 3. Calls pr() with the result returned from server u to add them to my# own list.# 4. Returns the new list. pr() and )]# 1. Checks the server list is not empty.# 2. Takes the first server on the list. Asks that server to augment its# server list with my URL.# 3. For each server on the returned list, asks it to add this server to its# list. (lambda sv:sv.register_function(f,"f") or srv(sv))(xs((ar,int(ar))))# Starts request processing.# 1. Defines a function with lambda expression that takes a SimpleXMLRPCServer# object, registers request handling function, f, and starts the server.# 2. Creates a SimpleXMLRPCServer object using hostname (ar) and portnum# (ar). Then feeds the object to the lambda function.# Running in client mode...for url in pxy(ar).f(pw(ar),0,[]):# 1. Create a ServerProxy object using the serverurl (ar).# 2. Calls the remote server and retrieves a server list.# 3. For each URL on the list, do the following:for fn in filter(lambda n:not n in ls(), (pxy(url).f(pw(url),1,ar))):# 1. Create a ServerProxy object using the URL.# 2. Calls the remote server to return a list of filenames matching the# pattern (ar).# 3. For each filename doesn't exist locally, do the following: (lambda fi:fi.write(pxy(url).f(pw(url),2,fn)) or fi.close())(file(fn,"wc")) # 1. Define a lambda function that takes a file object, calls remote server # for the file content, then closes the file. # 2. Create a file object in write and binary mode with the filename. (I # think the mode "wc" should be "wb".) # 3. Passes the file object to the lambda function.
页:
[1]