2007年10月11日 星期四

微型p2p檔案分享程式-要寫p2p的人要來參考哦!!

#!/bin/sh

# uP2P.sh: micro P2P file sharing application
# Version 0.0.1
# Written by P. Felber, 2005, pascal(dot)felber(at)unine(dot)ch

# This file is released to the public domain.
# Comments or suggestions are welcome!

# There is a short version of this script that fits in in less than 450
# characters (less that 6 lines of 80 characters).

########################################################################
# DESCRIPTION
#
# This shell script was inspired by Prof. Ed Felten's TinyP2P
# application (http://www.freedom-to-tinker.com/tinyp2p.html) and was
# developed as a follow-up to a seminar on peer-to-peer (P2P) networks
# organized at the University of Neuchatel. It sets up a small P2P
# network by sharing the content of the current directory with other
# peers. Files added to the directory at runtime are dynamically
# shared. With trivial modifications (documented in the code), it is
# also possible to share subdirectories.
#
# This shell script only uses standard Unix tools. Communication is
# handled using 'netcat' ('nc'), a command-line interface to TCP,
# installed by default on most Unix systems. It must be compiled to
# accept the '-e' flag (try 'nc -h' to verify); this is the case, for
# instance, with bootable Knoppix CDs. The script has been tested on
# various Linux distributions.
#
# Of course, the goal of this application is *NOT* to encourage illicit
# file sharing or facilitate copyright infringement (there exists far
# better and more scalable solutions), but to demonstrate how simple it
# is to create a non-trivial file sharing application.
#
# The network is password protected. In order to connect to the network
# or download a file, one needs to know the password.
#
# As each server knows of every other server, this application is not
# very scalable. It does, however, work remarkably well for exchanging
# files among small groups of people.

########################################################################
# USAGE
#
# To start a server, change to the directory that you would like to
# share and start the script as follows:
#
# uP2P.sh password local-ip local-port remote-ip remote-port
#
# where 'password' is the network's password; 'local-ip' and
# 'local-port' are the IP address and port used by the server for
# listening to remote requests; 'remote-ip' and 'remote-port' are the IP
# address and port of some other peer in the network. The first server
# can be started with any remote address (even its own address) since
# connections to non-existing endpoints will fail silently. All 5
# parameters must be specified.
#
# To start a client, change to the directory that you would like to
# download files to and start the script as follows:
#
# uP2P.sh password remote-ip remote-port pattern
#
# where 'password' is the network's password; 'remote-ip' and
# 'remote-port' are the IP address and port of some server peer in the
# network; 'pattern' is a filter that specifies the files to download
# using the 'grep' regular expression syntax. Note that, because of
# message forwarding, redundant escape characters must be used; for
# instance, "\." (dot) must be specified as "\\\\.".
#
# To end the script, kill all instances of 'nc'.

########################################################################
# EXAMPLE
#
# Start 4 servers on 4 hosts (or in different directories on the same
# host):
#
# uP2P.sh abc 192.168.1.100 9000 192.168.1.100 9000
# uP2P.sh abc 192.168.1.101 9000 192.168.1.100 9000
# uP2P.sh abc 192.168.1.102 9000 192.168.1.101 9000
# uP2P.sh abc 192.168.1.103 9000 192.168.1.101 9000
#
# Download all files containing 'pdf' in their name (here using third
# server as entry point to the network):
#
# uP2P.sh abc 192.168.1.102 9000 "pdf"

########################################################################
# LIMITATIONS
#
# - There are only few checks and error messages.
# - In theory, there might be some race conditions in rare situations,
# which might reduce availability or connectivity (this has never been
# experienced in tests, though).
# - Departures and failures are not handled explicitly: servers keep on
# forwarding messages to unreachable peers (which silently fails).
# - If there are subdirectories matching the search pattern in the
# shared directory of a server, an empty file with the same name as
# the subdirectory will be created by the client. This problem can be
# solved by slight additions to the script (documented in the code).
#
# The short version has the following additional limitations:
#
# - Even fewer checks and error messages.
# - The client does not verify if a file already exists locally before
# downloading it. This may result in unnecessary downloads.

########################################################################
# HOW IT WORKS
#
# - The server forks a new instance each time it processes a request, so
# that there is always a listener.
# - On startup, a new server sends a 'd' (discover) message to the
# existing server specified on the command line.
# - When receiving a 'd' message, a server returns its neighbor list to
# the new peer and forwards an 'a' (advertisement) message to
# all servers (including itself).
# - When receiving an 'a' message, a server adds the new peer to its
# neighbor list.
#
# - On startup, the client sends an 's' (search) request to the existing
# server specified on the command line.
# - When receiving an 's' message, a server forwards an 'l' (list)
# message to all servers (including itself).
# - When receiving an 'l' message, a server returns a list of the files
# that match pattern (each file comes with the host and port of the
# associated server).
# - Upon receiving the file list from all servers, the client sends 'g'
# (get) messages to download each file sequentially.

# Set common variables
[ $3 ]&&export W=$1 H="$2 $3"

# Make it a variable to save space
Z=/dev/null

# Echo arguments (make it a function to save space)
e(){ echo "$*"; }

# Invoke netcat (client mode)
n(){ nc $* 2>$Z; }

# Invoke netcat instance (server mode)
x(){ nc -lp ${H#* } -e $1 &>$Z <$Z& }

# Forward message to all neighbors
f(){ cat $K | while read h; do e $W $1 "$2" | n $h; done }

case $# in
# Client
4)
# Read file list and get each file from its source server (use quotes to allow spaces in filename)
e $W s "$4" | n $H | while read h p f; do [ -e "$f" ] || e $W g "$f" | n $h $p >"$f"; done
;;
# Server: first instance
5)
# Create temporary file
export K=`mktemp`
# Put our address in neighbor list
e $H >$K
# Discover peers (silently fails if no server is listening)
e $W d $H | n $4 $5 >>$K
# Start new instance
x $0
;;
# Server: child process
0)
# Test if variables are set (removed from short version)
: ${W?}${H?}${K?}
# Start new instance
x $0
# Read command
read w c r
[ $W = $w ]&&case $c in
# Search files: forward to all neighbors (including ourselves)
s) f l "$r" ;;
# Get file: just dump it to stdout (use quotes to allow spaces in filename)
g) cat "$r" ;;
# Announce peer: add to neighbor list
a) e $r >>$K ;;
# Discover peers: return our neighbor list and forward announcement
d) cat $K; f a "$r" ;;
# List files that match pattern and return triples (host port filename)
l) ls | grep "$r" | sed "s/^/$H /" ;;

# VARIANTS
#
# Longer version that checks file type:
#
# l) for i in `ls|grep "$r"`; do [ -f $i ] && e $H $i; done ;;
#
# Longer version that checks file type and searches subdirectories.
# The same subdirectories must exist on the client for transfers to
# succeed. The test '-name' can be changed to '-path', '-regex',
# etc.:
#
# l) find -name "$r" -type f -printf "$H $%f " ;;

esac
;;
esac

沒有留言: