Project 3

In this assignment, you are going to replace the TCP file transfer in the previous assignment with the UDP file transfer. Basically, you will implement a reliable file transfer mechanism on top of the unreliable UDP. This is achieved by implementing the Selective Repeat Protocol discussed in class. Because the protocol needs a timeout value, you will implement the timeout estimation algorithm used by TCP.

In this project, the server will be exactly the same as in the previous assignment. The files size should be changed to 100,000 in common.h:

#define FILE_LENGTH 100000

Then, the only change with regarding to the client is how it sends/receives the file, which is explained in the following.

Let’s say client A wants a file. Client A asks the server who has the file and the server replies with client B.

1.     Setting up a UDP connection.

a.     When client A receives the reply from the server about client B, it tries to connect to client B with client B’s listening port, and client B will accept this connection. Note that this connection is TCP.

b.     After the connection has been successfully set up, client A should get a new UDP socket, call it udp_socket_a, and call the bind function with INADDR_ANY as the IP address and 0 as the port number. The effect of this is that the system will find a port number to be associated with udp_socket_a.

c.     Client A then uses getsockname() to find the port number associated with udp_socket_a, and prints it out. Then, client A will tell client B the udp port number using the TCP connection with client B.

d.     When Client B receives the port number from client A, it prints out this port number. Then, client B will fork off a new process by calling the fork() function. The child process, denoted as B’, will be in charge of sending the file to client A.  

e.     B’ will get a new udp socket, call it udp_socket_b, and calls the bind function with INADDR_ANY as the IP address and 0 as the port number. B’ will then find out the udp port number associated with udp_socket_b¸ prints it out, and send it to client A using the TCP connection with A. B’ will also use connect() function to connect udp_socket_b with client A’s IP address and the udp port number associated with udp_socket_a.

f.      When client A receives the message from B’, client A prints out the port number. Client A will also use connect() function to connect udp_socket_a with B’s IP address and the udp port number associated with udp_socket_b. Connecting two UDP sockets makes the coding a little simpler; you don’t have to specify the remote address every time. Now B’ can send data to client A simply by calling the send() function with upd_socket_b as one of the parameters, and the format will be exactly the same as sending data through TCP sockets. Similarly, B’ can receive data from A by calling the recv() function with upd_socket_b as one of the parameters, and the format will be exactly the same as receiving data through TCP sockets.

g.     Note that B’ will inherit all open file descriptors from B, but it should not process any message sent to client B because its only job is to send the file to client A. In fact it needs only one socket, udp_socket_b. So B’ will close all other opening file descriptors inherited from client B by calling the close() function.

 

2.     The protocol. Now Client A and B’ has set up a connection with UDP. B’ will get the file in the buffer, and starts sending. Client A and B’ uses the Selective Repeat Protocol for the file transfer. In this project, the sender and receiver window size are both set to 10, and each slot holds 1000 bytes. We call each 1000 bytes of the file a block. In this project, the sequence number can be 16 bits so you don’t have to worry about the wrap around of sequence numbers. However, you can only use a buffer of 10 blocks, so you need to worry about the wrap around of buffer pointer. Also, you should implement the timeout of packets by the select function.

 

The protocol is:

Sender. Assume the current window is m+1 to m+n.

while (1) { 

           If network layer has data and if current window not full yet: read data, send to physical layer with the current sending frame ID, start timer, increment sending ID.

           If got ACKw: if w is outside the window, don’t do anything; if w is inside the window, consider all frames in the window with ID no more than w acked and let m=w.

           If timeout for frame w, resend frame w.

}

Receiver. Assume the current window is m+1 to m+n.

while (1)  {

           Wait (blocked here) and get frame from the physical layer. If it is within the receiver window and hasn’t been received before, fill in the slot,  forward the beginning of the receiver window if necessary, and deliver to the network layer all frames between the beginning of the old receiver window and the new receiver window – 1, inclusive. Send ACKm (m+1= the beginning of the current receiver window).

} 

Note: assuming the sequence number is the frame ID.

Note: for simplicity, assume the receiver network layer is always ready.

 

Print out:

·        Whenever the receiver receives a frame, it prints out a line starting with the current unix time (in microsecond), including the sequence number of the received frame, the current window, and the type of action it will take, such as “12345678: Client 1 received frame seqnum 10, window [10-19], taking this frame, sending ACK 10.”  It does not need to follow the exact format, but should contain similar information.

·        Whenever the sender receives an ACK, it prints out a line starting with the current unix time, including the sequence number of the received ACK, the current window, and the type of action it will take, such as “12345678: Client 2 received ACK seqnum 10, curr window [9-18], moving window to [11-20].”  It does not need to follow the exact format, but should contain similar information.

·        Whenever the receiver sends an ACK, it prints out a line starting with the current unix time, including the sequence number of the ACK and the current window, such as “12345678: Client 2 sending ACK seqnum 8, window [9-18].”  It does not need to follow the exact format, but should contain similar information.

·        Whenever the sender sends a frame, it prints out a line starting with the current unix time, including the sequence number of the frame and the current window, such as “12345678: Client 2 sending frame seqnum 15, window [9-18].”  It does not need to follow the exact format, but should contain similar information.

·        The above are the necessary outputs to check the progress of your code. You can also include other print out of your own.

 

 

3.     Simulating packet loss and delay. When Client A gets a UDP data packet from B’, with probability p, it drops it, where p is a parameter. For the received UDP data packet that is not dropped, with probability p, client A does not send ACK at all. If client A sends ACK, it does not do so immediately; instead, it delays for a random amount of time to emulate the network delay. The length of the delayed time is a random variable with value randomly taken from 50ms to 150 ms. Your client program should be augmented to be able to take the parameter p when invoked in the format: “-l 0.1”. 

 

Print out:

·        Whenever the receiver drops a packet, it prints out a line starting with the current unix time, including the sequence number of the frame dropped, such as “12345678: Client 2 dropping frame seqnum 15.”

·        Whenever the receiver drops an ACK, it prints out a line starting with the current unix time, including the sequence number of the ACK dropped, such as “12345678: Client 2 dropping ACK seqnum 15.”

 

4.     Estimating RTT. B’ estimates the RTT (Round Trip Time) time by the algorithm used by TCP.

·        RTT_new = (1-g) * RTT_old  + g * RTT_sample,

·        D_new = (1-h) * D_old + h * |RTT_sample - RTT_old|,

where D denotes the estimation of the variance, and g=0.125, h=0.25. RTT_sample is obtained by measuring time elapsed between sending a frame and receiving the ACK for this frame. It is suggested that when the sender sends a frame, it puts the current time into this frame, and when the receiver sends ACK, it should echo this field back in the ACK. Note that every received frame will trigger an ACK; so if the sender receives an ACK, it knows the RTT of the frame that triggered this ACK. The timeout TO is set to be

·        TO = RTT + 4D

In our implementation, it is suggested that the initial value of the RTT is set to be 100ms and initial value of D is set to be 0.

Print out:

·        Whenever the sender gets ACK for a frame, it performs the above calculation, and prints out a line starting with the current unix time, including the new measured RTT_sample, RTT_new, D_new, and TO.

 

5.     Closing the connection. After B’ received the ACK for the last block, B’ sends 10 FIN frames and quits. Client A does not drop the FIN frame. When client A gets a FIN frame, client A quits.

Print out:

·        When the sender sends FIN, it prints out a line starting with the current unix time and then indicating that it has quitted. When the receiver gets FIN, it prints out a line starting with the current unix time and then indicating that it has quitted.