Vous êtes sur la page 1sur 12

Internet Engineering Course Socket Programming Project Spring 2011

Adapted from: Mr. Viney Kheras course project at University of Southern California Instructor: Dr. Mohammad Nassiri Bu-Ali Sina University, Hamedan

The objective of this assignment is to familiarize you with UNIX socket programming. This assignment is worth 25% of your overall grade in this course. You have to work as a team of 2 students to do this programming assignment. Any cheating will result in an automatic F in the course (not just in the assignment).

The Problem:
In this project you will be simulating transfer of fragmented messages over TCP and UDP sockets in a network with client-server architecture. The project has 3 major phases: Fragmentation/distribution, Routing and Verification. In Phase 1, all communications are through TCP sockets. In phases 2 and 3 however, all communications are over UDP sockets.

Code and Input files:


You must write your programs either in C or C++ on UNIX. In fact, you will be writing (at least) 3 different pieces of code: 1- Messenger a. You must use one of these names for this piece of code: messenger.c or messenger.cc or messenger.cpp (all small letters). Also you must call the corresponding header file (if any) messenger.h (all small letters). You must follow this naming convention. 2- Router a. You must create 3 concurrent Routers i. Either by using fork() or a similar Unix system call. In this case, you probably have only one piece of code for which you need to use one of these names: router.c or router.cc or router.cpp (all small letters). Also you must call the corresponding header file (if any) router.h (all small letters). You must follow this naming convention. ii. Or by running 3 instances of the Router code. However in this case, you probably have 3 pieces of code for which you need to use one of these sets of names: (router1.c, router2.c, router3.c) or (router1.cc, router2.cc, router3.cc) or (router1.cpp, router2.cpp and router3.cpp) (all small letters). Also you must call the corresponding header file (if any) router.h (all small letters) or router1.h, router2.h and router3.h (all small letters). You must follow this naming convention. 3- Receiver

a. You must create 2 concurrent Receivers i. Either by using fork() or a similar Unix system call. In this case, you probably have only one piece of code for which you need to use one of these names: receiver.c or receiver.cc or receiver.cpp (all small letters). Also you must call the corresponding header file (if any) receiver.h (all small letters). You must follow this naming convention. ii. Or by running 2 instances of the Router code. However in this case, you probably have 2 pieces of code for which you need to use one of these sets of names: (receiver1.c, receiver2.c) or (receiver1.cc, receiver2.cc) or (receiver1.cpp, receiver2.cpp) (all small letters). Also you must call the corresponding header file (if any) receiver.h (all small letters) or receiver1.h, receiver2.h (all small letters). You must follow this naming convention. 4- Input file : message.txt a. There is one input file for this project, message.txt. This input file contains two English sentences. Here is the format of a sample input file: 5 This is the IE892 class 7 We are in the Spring 2011 semester In this sample input file each line starts with a number between 2 and 8 which corresponds to the number of words in the sentence on that line. In this example, the number of words in the first sentence is 5 and the number of words in the second sentence is 7. As can be seen the delimiter used between the words is one space. You are given a sample input file message.txt to test your code, however when your project is graded, the TA may use a different input file with the exact same format to test your project. Please note that there are always two lines (hence only two sentences) in this file.

A more detailed explanation of the problem:


This project is divided into 3 phases. It is not possible to proceed to one phase without completing the previous phase and in each phase you will have multiple concurrent processes that will communicate either over TCP or UDP sockets. Phase1: In this phase, Messenger opens the input file and reads the contents of the file (i.e. the two English sentences) and generates some packets using a specific header format (shown in Figure1). Each packet carries (or encapsulates) exactly one English word as its payload or data. For example with the current input file, Messenger will create a total of 12 packets (5 packets for the words in sentence #1 and 7 packets for the words in sentence#2). The packets that carry words of sentence#1 are destined for Receiver#1 and packets that carry words of sentence#2 are destined for Receiver #2. Next, Messenger must contact the 3 Routers in a round-robin fashion to distribute these packets among them over TCP sockets. Therefore Messenger must know the TCP port number of each Router in advance. In other words you must hardcode the TCP port number of each Router, in the Messenger code. Table 1 shows how static TCP and UDP port numbers should be defined for each entity in this project. Messenger will use 3 different dynamically-assigned TCP port numbers (NOT statically defined) and establishes 3 TCP connections to 3 Routers. You are free to implement these 3 TCP connections either in

parallel or serially. In other words, Messenger can use its first TCP port number and establish a TCP connection to Router1, send all the necessary packets to Router1and close this connection. It can then repeat this process for Router#2 and Router #3 serially. Its also possible for Messenger to open 3 concurrent or parallel TCP connections to 3 Routers over 3 different TCP port numbers. This is entirely your choice to implement this part in parallel or serially.

Whether the TCP connections are established serially or in parallel, the packets that are required to be transferred to each Router are pre-determined based on the contents of the input file. For example with the given sample input file, packet #1,#4,#7 and #10 will be sent to Router1, packet #2, #5, #8 and #11 will be sent to Router #2 and packets #3, #6, #9 and #12 will be sent to Router #3. Please note that in this case each Router

Identifier String

Sentence# Fragment#

Total

Payload

Any of the following strings: Messenger, Router1,Router2, Router3, Receiver1, Receiver2

1 or 2

The word Total number number in Of words in this sentence this sentence

Either a single English word or a complete English Sentence

(a)

Messenger

IE892

(b)
In this example word#4 in sentence#1 with a total of 5 words is encapsulated

in a packet sent from Messenger to Receiver1

This is the IE892 class


Figure1: (a) General format of a message (b) An example
Messenger

TCP

Dynamic TCP Port #1 Dynamic TCP Port #2 TCP

Dynamic TCP Port #3

TCP

Static TCP Port = 21100+xxx


CISCOSYSTEMS

Router1

Static TCP Port = 21300+xxx Router2


3Com

Static TCP Port = 21200+xxx

Receiver1

Receiver2

Figure2: Phase 1, Fragmentation and distribution of fragments

Messenger

Router1
CISCOSYSTEMS

Router3 Dynamic UDP Port

Dynamic UDP Port UDP UDP Receiver1 UDP

Router2
3Com

Dynamic UDP Port UDP Receiver2

UDP UDP

Static UDP Port =3100+xxx

Static UDP Port =3200+xxx

Figure3: Phase 2, Routing

receives the same number of packets because there are a total of 12 English words in the input file and 12 is evenly divisible by 3 (the number of Routers). However in the test-case used for grading, the total number of words may not be a multiple of 3, hence some Routers may receive less packets than others. Your code should work for the general case. Figure2 illustrates phase1 of this project. Phase2: In phase2 of this project, each Router must inspect the header of each data packet (received from Messenger), correctly identify the destination of each packet and forward them through the correct outgoing interface toward the destination. In this case the outgoing interface corresponds to a UDP socket. Since there are two Receivers in this project, each Router has two outgoing interfaces, in other words you must hardcode the static UDP port for each Receiver inside the Router code. Each Router will then change the identifier string in the packet, from Messenger to its name (i.e. Router1, or Router2 or Router3).It must then create a UDP socket to communicate with a Receiver and send the packets that are destined for that Receiver over that UDP socket. The Routers can contact the Receivers in any arbitrary order. Upon successful completion of this phase, Receiver1 should have received all the words in sentence#1 and Receiver2 should have received all the words in sentence#2. Figure3 illustrates the communications over UDP sockets in phase2.

Messenger

UDP
CISCOSYSTEMS

Static UDP Port =4100+xxx Router1 Router3

UDP

Router2
3Com

Receiver1

Receiver2

Dynamic UDP Port

Dynamic UDP Port

Figure4: Phase 3, Verification

Phase3: In this phase, each Receiver must assemble the words that it received in phase2, in the correct order and form the original sentence. Each Receiver then generates one packet (according to the provided format in Figure #1) that carries the complete sentence as its payload. It then creates a new UDP socket to communicate with Messenger and sends that packet to Messenger. It is therefore implied that Messenger has a UDP port number that is statically defined and is already hardcoded in both Receiver codes. Messenger will then extract the payload of each packet received from each Receiver, compares it to the corresponding sentence in the input file, e.g. if the packet is received from receiver1 it will be compared to sentence#1 and verifies whether it is a match. It will then announce the results on the screen. This marks the end of Phase3, i.e. the verification. Table 1: A Summary of Static and Dynamic assignment of TCP and UDP Ports and IP addresses IP address Process Dynamic ports Static Ports obtained from Messenger 3 TCP Ports (Phase1) 1 UDP Port, 4100+ xxx of your ID (Phase3) local host Router1 1 UDP Port (Phase2) 1 TCP Port, 21100+ xxx of your ID (Phase1) local host Router2 1 UDP Port (Phase2) 1 TCP Port, 21200+ xxx of your ID (Phase1) local host Router3 1 UDP Port (Phase2) 1 TCP Port, 21300+ xxx of your ID (Phase1) local host Receiver1 1 UDP Port (Phase3) 1 UDP Port, 3100+ xxx of your ID (Phase2) local host Receiver2 1 UDP Port (Phase3) 1 UDP Port, 3200+ xxx of your ID (Phase2) local host

On-screen Messages:
In order to clearly understand the flow of the project, your codes must print out the following messages on the screen as listed in the following Tables. Table 2: Messenger on-screen messages Event Upon Startup Upon establishing a connection to each Router Sending a data Packet to a Router Upon sending all the required packets to a Router Receiving an ack Packet from a Router Receiving a data Packet from a Receiver Upon matching sentence# with the one in the input file End of Phase1 and Phase3 On-screen Message Messenger has TCP Ports UDP Port . and IP address Messenger is now connected to <Router#> Sent <packet#> containing <payload> to <Router#> over <socket type> Completed transfer of <number of packets> Packets to <Router#> Received Ack for <packet#> from <name of sender> over <socket type> Received The Sentence <payload> from <Receiver#> over <socket type> Sentence# is a match End of Phase# for Messenger

Table 3: Router on-screen messages Event Upon Startup On-screen Message <Router#> has TCP Port UDP Port . and IP address

Received <packet#> containing <payload> from Messenger over Receiving a data Packet from <socket type> Messenger Upon accepting a connection <Router#> accepted connection request from Messenger request from Messenger Forwarded <packet#> containing <payload> to <Receiver#> over Sending a data Packet to a <socket type> Receiver Completed transfer of <number of packets> Packets to Upon sending all the required <Receiver#> packets to a receiver End of Phase1 and Phase2 End of Phase# for <Router#>

Event Upon Startup Receiving a data Packet from a Router Sending a data Packet to Messenger End of Phase2 and Phase3 Assumptions:

Table 4: Receiver on-screen messages On-screen Message <Receiver#> has UDP Ports . and IP address Received <packet#> containing <payload> from<Router#> over <socket type> Forwarded sentence# to Messenger over <socket type> End of Phase# for <Receiver#>

1. The Processes are started in this order: Router, Messenger and receiver. 2. For each data packet sent over a TCP socket, an Ack packet is returned. An Ack packet is simply the string ack (small letters, without the quotes). Like all other messages in this project, a message containing an ack must also start with an identifier string. 3. If you need to have more code files than the ones that are mentioned here, please use meaningful names and all small letters and mention them all in your README file. 4. You are allowed to use blocks of code from Beejs socket programming tutorial (Beejs guide to network programming) in your project. 5. When you run your code, if you get the message port already in use or address already in use, please first check to see if you have a zombie process (from past logins or previous runs of code that are still not terminated and hold the port busy). If you do not have such zombie processes or if you still get this message after terminating all zombie processes, try changing the static UDP or TCP port number corresponding to this error message (all port numbers below 1024 are reserved and must not be used). If you have to change the port number, please do mention it in your README file. Requirements: 1. Do not hardcode the TCP or UDP port numbers that must be obtained dynamically. Refer to Figures 2 through 4 and Table1 to see which ports are statically defined and which ones are dynamically assigned. Use getsockname() function to retrieve the locally-bound port number wherever ports are assigned dynamically as shown below: //Retrieve the locally-bound name of the specified socket and store it in the sockaddr structure getsock_check=getsockname(TCP_Connect_Sock,(struct sockaddr *)&my_addr, (socklen_t *)&addrlen) ; //Error checking if (getsock_check== -1) { perror("getsockname"); exit(1); }

2. Use gethostbyname() to obtain the IP address of the local host. 3. You can either terminate all processes after completion of phase3 or assume that the user will terminate them at the end by pressing ctrl-C. 4. All the naming conventions and the on-screen messages must conform to the previously mentioned rules. 5. All messages sent through sockets must start with an identifier string as instructed in the project description. 6. You are not allowed to pass any parameter or value or string or character as a command-line argument. No user interaction must be required (except for when the user runs the code obviously). Every thing is either hardcoded or dynamically generated as described before. 7. All the on-screen messages must conform exactly to the project description. You must not add anymore onscreen messages. If you need to do so for the debugging purposes, you must comment out all of the extra messages before you submit your project. 8. Using fork() or similar system calls are not mandatory if you do not feel comfortable using them to create concurrent processes. 9. Please do remember to close the socket and tear down the connection once you are done using that socket.

Programming languages and compilers: You must use only C/C++ on UNIX as well as UNIX Socket programming commands and functions. Here are the pointers for Beej's Guide to C Programming and Network Programming (socket programming): http://www.beej.us/guide/bgnet/ (If you are new to socket programming please do study this tutorial carefully as soon as possible and before starting the project) http://www.beej.us/guide/bgc/ You can use a unix text editor like emacs (or vi/vim) to type your code and then use compilers such as g++ (for C++) and gcc (for C). To compile your code. You must use the following commands and switches to compile yourfile.c or yourfile.cpp. It will make an executable by the name of "yourfileoutput. gcc -o yourfileoutput yourfile.c -lsocket g++ -o yourfileoutput yourfile.cpp -lsocket -lnsl -lnsl -lresolv -lresolv

Do NOT forget the mandatory naming conventions mentioned before! Also inside your code you need to include these header files in addition to any other header file you think you may need:
#include <stdio.h> #include <stdlib.h> #include <unistd.h>

#include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> #include <sys/wait.h>

Submission Rules: 1. Along with your code files, include a README file. In this file write a.Your Full Names as given in the class list b.Your Student IDs c. What you have done in the assignment d. What your code files are and what each one of them does. (Please do not repeat the project description, just name your code files and briefly mention what they do). e. What the TA should do to run your programs. (Any specific order of events should be mentioned.) f. The format of all the messages exchanged (other than what is mentioned in the project description). g. Any idiosyncrasy of your project. It should say under what conditions the project fails, if any. h. Reused Code: Did you use code from anywhere for your project? If not, say so. If so, say what functions and where they're from. (Also identify this with a comment in the source code.) Submissions WITHOUT README files WILL NOT BE GRADED. 2. Compress all your files including the README file into a single tar ball and call it: IE892_username1_username2_univ.tar.gz (all small letters) e.g. my file name would be ie892_nassiri_basu.tar.gz. Here are the instructions: a. On your host, go to the directory which has all your project files. Remove all executable and other unnecessary files. Only include the required source code files and the README file. Now run the following commands: b. tar cvf ie892_username1_username2_univ.tar * - Now, you will find a file named ie892_username1_username2_univ.tar in the same directory. c. gzip ie892_username1_username2_univ.tar Now, you will find a file named ie892_username1_username2_univ.tar.gz in the same directory. Grading Criteria: Your project grade will depend on the following: 1. Correct functionality, i.e. how well your programs fulfill the requirements of the assignment, specially the

communications through UDP and TCP sockets. 2. Inline comments in your code. This is important as this will help in understanding what you have done. 3. Whether your programs work as you say they would in the README file. 4. Whether your programs print out the appropriate error messages and results. 5. If your submitted codes, do not even compile, you will receive 10 out of 100 for the project. 6. If your submitted codes, compile but when executed, produce runtime errors without performing any tasks of the project, you will receive 10 out of 100. 7. If your codes compile but when executed only perform phase1 correctly, you will receive 40 out of 100. 8. If your codes compile but when executed perform only phase1 and phase 2 correctly, you will receive 80 out of 100. 9. If your code compiles and performs all tasks in all 3 phases correctly and error-free, and your README file conforms to the requirements mentioned before, you will receive 100 out of 100. 10. If you forget to include any of the code files or the README file in the project tar-ball that you submitted, you will lose 5 points for each missing file (plus you need to send the file to the TA in order for your project to be graded.) 11. If your code does not correctly assign the TCP or UDP port numbers dynamically (in any phase), you will lose 20 points. 12. You will lose 5 points for each error or a task that is not done correctly. 13. The minimum grade for an on-time submitted project is 10 out of 100. 14. There are no points for the effort or the time you spend working on the project or reading the tutorial. If you spend about 2 months on this project and it doesnt even compile, you will receive only 10 out 0f 100. 15. Using fork() or similar system calls are not mandatory however if you do use fork() or similar system files in your codes to create concurrent processes (or threads) and they function correctly you will receive 10 bonus points. 16. If you submit a makefile or a script file along with your project that helps us compile your codes more easily, you will receive 5 bonus points. 17. The maximum points that you can receive for the project with the bonus points is 100. In other words the bonus points will only improve your grade if your grade is less than 100. 18. Your code will not be altered in any ways for grading purposes and however it will be tested with different input files. Your designated TA runs your project as is, according to the project description and your README file and then check whether it works correctly or not. Cautionary Words:

1. Start on this project early!!! 2. In view of what is a recurring complaint near the end of a project, we want to make it clear that the target platform on which the project is supposed to run is a linux-based host. It is strongly recommended that students develop their code on a linux-based host like Ubuntu. 3. You may create zombie processes while testing your codes, please make sure you kill them every time you want to run your code. To see a list of all zombie processes even from your past logins, try this command: ps aux | grep <your_username> 4. Identify the zombie processes and their process number and kill them by typing at the command-line: 5. Kill -9 processnumber 6. Please do remember to terminate all zombie or background processes; otherwise they hold the assigned port numbers and sockets busy.

Academic Integrity: All students are expected to write all their code on their own. Copying code from friends is called plagiarism not collaboration and will result in an F for the entire course. Any libraries or pieces of code that you use and you did not write, must be listed in your README file. All programs will be compared with automated tools to detect similarities; examples of code copying will get an F for the course. I didnt know is not an excuse.