CSCI 5211 Fall 2015 Programming Project Peer-to-Peer (P2P) File Sharing System In this programming assignment, you are asked to develop a simple peer-to-peer (P2P) file sharing system. The objective of this project is to let you get hands-on experiences in computer network programming, in particular, socket programming, and in network application development. You are asked to develop two programs, called 'central-server' and 'peer'. 'central-server' is used to store the information of 'peer's (e.g., peer ID, peer Name, IP address, port number). 'peer's need to register themselves to 'central-server' and 'central-server' returns the connecting information to 'peer's. Multiple hosts execute the program 'peer' in certain order (which will be elaborated later) to form a P2P system. We call such a host with a running 'peer' program as a peer host. Every peer host designates a directory containing several files as its shared directory when it starts working. Once a peer-to-peer system is set up, any peer host can use command 'get' to download the specified file from some peer hosts holding the file. There are multiple peer hosts and one central server. You must finish this programming project individually. Note: The file sharing is only among the peers, not the 'central-server'. 'central-server' does not participate in the file downloading. Forming a P2P System In order to form a P2P system, the 'central-server' should be created by the following command. central-server [optional argument1] [optional argument2]... After the central-server is created, a peer host can register itself to the central-server and join the P2P network by the following command. peer pathname central-server-name [optional argument1] [optional argument2]... Here, 'pathname' designates the shared directory of a peer host running this program. 'central-servername' is name of the central-server that has been created. After this command, the following operations should be finished. 1) The peer host registers itself to the central-server. 2) The central-server looks up its records, randomly picks up an existing peer host and returns its name to the new peer host. Then this new peer host will join the P2P system by connecting to this existing peer host. If there is no peer host (the new requesting peer host is the first one to register), the central-server does not return the name of existing peer host, and instead, it can return a confirmation message to the new peer host to let the new peer host form a P2P network. (After that, there is only one peer host in the P2P network.)
To make things clear, we assume the name of the existing peer host returned by central-server is "A". And the new requesting peer host is called "B". After the new requesting peer host B receives the name of existing peer host A from the central server, B sets up a connection to A. Then, we say A and B are neighbors. Note: 'central-server' and 'peer' are not neighbors. An Example: Assuming you have compiled the source files and generated the binary 'central-server' and 'peer'. Before started, you copy 'peer' to your CS account home directory '/home/grad04/xiang' Step 1: create directories and files on different hosts xiang@cello (~) % mkdir /home/grad04/xiang/cello xiang@cello(~) % echo "this is mydoc1" > /home/grad04/xiang/cello/mydoc1 xiang@saxophone (~) % mkdir /home/grad04/xiang/saxophone xiang@saxophone (~) % echo "this is mydoc2" > /home/grad04/xiang/saxophone/mydoc2 xiang@oboe (~) % mkdir /home/grad04/xiang/oboe xiang@oboe (~) % echo "this is mydoc3" > /home/grad04/xiang/oboe/mydoc3 xiang@trombone (~) % mkdir /home/grad04/xiang/trombone xiang@trombone (~) % echo "this is mydoc4" > /home/grad04/xiang/trombone /mydoc4 Step 2: start central-server on 'flute'. xiang@flute (~) % central-server [optional argument1] [optional argument2]... Step 3: start peer host on 'cello', registering and joining the P2P system xiang@cello (~) % peer /home/grad04/xiang/cello flute.cs.umn.edu [optional argument1] [optional argument2]... Step 4: start peer host on 'saxophone', registering and joining the P2P system xiang@saxophone (~) % peer /home/grad04/xiang/saxophone flute.cs.umn.edu [optional argument1] [optional argument2]... Step 5: start peer host on 'oboe', registering and joining the P2P system xiang@oboe (~) % peer /home/grad04/xiang/oboe flute.cs.umn.edu [optional argument1] [optional argument2]... Step 6: start peer host on 'trombone', registering and joining the P2P system xiang@trombone (~) % peer /home/grad04/xiang/trombone flute.cs.umn.edu [optional argument1] [optional argument2]... Step 7: on peer host 'cello', type in command get mydoc4 The file 'mydoc4' should be downloaded from 'trombone' to 'cello' and stored in the designated directory of the 'peer' program. In this example, you should find the downloaded file at '/home/grad04/xiang/cello/mydoc4'. Lookup service After the peer-to-peer system is set up, a user can type the command like 'get mydoc4' on a peer host to download the specified file. This actually involves two steps - lookup and download. The lookup service used in this simple file sharing system is based on flooding. In the previous example, after 'get
mydoc4' is input on peer host 'cello', a message which looks like 'GET mydoc4 128.101.189.164 36953' is constructed. In this message, '128.101.189.164' is the IP address of host 'cello'. '36953' is the port number of the listen socket that 'cello' has created to set up a data channel (or TCP connection) with the peer which has 'mydoc4'. This message is flooded to all neighbors of 'cello'. For every peer host receiving this message, they first do a local lookup to see whether the specified file is in its shared directory. If it is not there, the peer host forwards the same message to all of its known neighbors, except the one from which it got the message. If the specified file is in a peer host's shared directory, it makes a connection request to the originating peer host whose IP address and port number is in the message (in this example, it should make a connection to host 128.101.189.164 at port 36953). Once the connection is set up, the requested file is sent. If the requested file has multiple copies in different peers, the peer which requests this file will download it from the peer which first makes the file transfer connection, and rejects other peers' file downloading connections. Note: The peer hosts transmitting files between each other are not neighbors. In the previous example, although "cello" gets 'mydoc4' from "trombone" and a connection is built between them, they are not considered as neighbors. The following figure shows one possible P2P topology of the previous example.
Download Files considering Timeout A new listen socket needs to be created when a 'get' command is received from stdin. Since this listen socket has a timeout requirement, you can use select() with timeout period, e.g., 5 seconds, to wait for connection requests on the listen socket. In the example, 'cello' creates a listen socket waiting for connection request from some peer host holding 'mydoc4'. However, it is possible that 'mydoc4' does not exist in any peer host. To handle this case, such listen socket has a timeout period, for example, 5 seconds. If there is no connection setup after timeout, the listen socket is closed and a message admin: the requested file does not exist in the P2P system should be displayed by your programs. On the other hand, when the download is completed, a message the requested file has been downloaded successfully should be shown. Servicing the Files downloaded from Other Peers After a peer downloads a new file from another peer, the file can be provided to other peers which request it. Therefore, you need to update the file list after completing each download. For example, assume that 'saxophone' downloaded 'mydoc4' from 'trombone' and 'oboe' requests 'mydoc4'. Since 'saxophone' has 'mydoc4' now, it can provide it for 'oboe' instead of 'trombone'. Terminate a Peer Host Use 'quit' to terminate a copy of 'peer' and 'central-server'. It is required that the termination is handled gracefully (e.g., the connected neighbor(s) should display a message like "admin: disconnected from 'saxophone.cs.umn.edu(35032)' " if 'saxophone' is shut down). Be assured that there is no crash on any neighboring peers. The remaining peer hosts must work correctly. Commands you must support in the peer program 1) get: to download a file from other peers. 2) list: to display file lists in its own shared directory. 3) quit: to terminate a peer host. Miscellaneous This programming project must be finished individually. We assume there are no more than 10 peers in the P2P system. In order to simplify the problem, we can assume that a peer does not download a file that has existed in its designated shared directory, even if the two files with the same file name have different contents. For example, if a peer host A has the file mydoc1 in its directory, it will not download mydoc1 from other peers, even if the file mydoc1 in other peers directories have different contents from mydoc1 in peer host A s directory. In other words, you do not need to consider file overwrite or replacing existing files. You can use command line "gcc -lsocket -lnsl peer.c -o peer" under Solaris, or use "gcc -lnsl peer.c -o peer" under Linux to compile your source files. As long as your final programs have the mentioned functions (including output messages) and work well in UNIX or LINUX, they will be acceptable. Any programming language is acceptable. You must make sure that you programs work well in CS or CSELabs machines. Your programs must be able to work on multiple machines, i.e., the central server and each peer host should run on
different machines. For example, if you have 5 peers, these 5 peers should run on 5 different machines respectively. Also, the central server should run on another machine different from these 5 machines. You need to consider some error handlings (e.g., peer registering to a non-existing central server, invalid commands, downloading a non-existing file). If one peer terminates by 'quit', you do not need to consider re-connecting the two separated parts together. However, you need to make sure the two separated parts work well respectively. Your programs should output some proper messages after each command and operation. A readme file should be provided in the submission to explicitly show how to compile and run your programs. Milestones 11/02 (Monday): First submission (partial running programs). Your 'peer' and 'central-server' programs need to show successfully constructing P2P network. Other requirements do not need to be provided. 12/07 (Monday): Final submission (complete programs). You must submit your Makefile (if necessary) as well as all other files. Note: The project will be graded based on the final submission (due 12/07), but you are required to do the first submission (due 11/02). Please compress all your files to.tar or.zip (not.rar) for convenience. You use "Last name + StudentID.tar (or.zip)" to name your submission file. Please submit your compressed file to Moodle website: https://ay15.moodle.umn.edu/course/view.php?id=7756