Montana Tech of The University of Montana
Computer Science & Software Engineering

CSCI 466
Fall 2013

Program #3 - Reliable Data Transport

In this program, you will put into practice the basic building blocks of reliable data transport: acknowledgements, checksums and timeouts.

Overview. You will be writing the sending and receiving transport-level code for implementing a simple reliable data transfer protocol. You will be using the alternating-bit-protocol (rdt3.0 from Chapter 3). In this program, you will practice what we've learned about reliable data transport by implementing a simulated stop-and-wait sender and receiver. This lab should be fun since your implementation will differ very little from what would be required in a real-world situation. Your code will execute in a simulated hardware/software environment. However, the programming interface provided to your routines, i.e. the code that would call your entities from above and from below is very close to what is done in an actual UNIX environment. Stopping/starting of timers are also simulated, and timer interrupts will cause your timer handling routine to be activated.

The routines you will write. The procedures you will write are for the sending entity (A) and the receiving entity (B). Only unidirectional transfer of data (from A to B) is required. Of course, the B side will have to send packets to A to acknowledge receipt of data. Your routines are to be implemented in the form of the procedures described below. These procedures will be called by (and will call) procedures that I have written which emulate a network environment. Here is the overall structure of the environment:

The unit of data passed between the upper layers and your protocols is a message, which is declared as:
struct msg 
   char data[20];
This declaration, and all other data structure and emulator routines, as well as stub functions (which you need to complete) are in the C++ source file, rdt.cpp. It is a command-line program, so you can use the operating system and development environment of your choice. But I will be compiling it with g++ on katie and testing it there as well.

Your sending entity will thus receive data in 20-byte chunks from layer5. Your receiving entity should deliver 20-byte chunks of correctly received data to layer5 at the receiving side. The unit of data passed between your routines and the network layer is the packet, which is declared as:
struct pkt {
   int seqnum;
   int acknum;
   int checksum;
   char payload[20];
Your routines will fill in the payload field from the message data passed down from layer5. The other packet fields will be used by your protocols to insure reliable delivery, as we've seen in class.

The routines you will write are detailed below. As noted above, such procedures in real-life would be part of the operating system, and would be called by other procedures in the operating system.
Software Interfaces. The procedures described above are the ones that you will write. I have written the following routines which can be called by your routines:
The simulated network environment.

A call to procedure tolayer3() sends packets into the medium (i.e. into the network layer). Your procedures A_input() and B_input() are called when a packet is to be delivered from the medium to your protocol layer.

The medium is capable of corrupting and losing packets. It will not reorder packets. When you compile your procedures and my procedures together and run the resulting program, you will be asked to specify values regarding the simulated network environment:


You are to write the procedures, A_output(),A_input(),A_timerinterrupt(),A_init(),B_input(), and B_init() which together will implement a stop-and-wait (i.e. the alternating bit protocol, which we referred to as rdt3.0 in the text) unidirectional transfer of data from the A-side to the B-side. Your protocol should only use positive acknowledgements with the receiver sending an ACK of the last good packet if a corrupted or out-of-sequence packet is received.

You should choose a very large value for the average time between messages from sender's layer5, so that your sender is never called while it still has an outstanding, unacknowledged message it is trying to send to the receiver. I'd suggest you choose a value of 1000. You should also perform a check in your sender to make sure that when A_output() is called, there is no message currently in transit. If there is, you can simply ignore (drop) the data being passed to the A_output() routine.

Helpful Hints.
Example runs. Below are some input and output files. Your output can of course differ in some ways (e.g. you may have choosen a different way to compute checksums). In our solution, we used a flag value of 255 when the acknowledgement or sequence number was unused. We used 15.0 as the timeout value.

rdt < 10_noerr_trace2.txt > 10_noerr_trace2.out
rdt < 10_noerr_trace3.txt > 10_noerr_trace3.out
rdt < 10_corrupt_trace2.txt > 10_corrupt_trace2.out
rdt < 10_corrupt_trace3.txt > 10_corrupt_trace3.out
rdt < 10_trace2.txt > 10_trace2.out
rdt < 10_trace3.txt > 10_trace3.out

Submission. Submit your program rdt.cpp via Moodle. Be sure each submitted source file has the required header with your name, username, and a description of the program. If you worked as a pair, submit only one copy of the source code with both your names on it. Programs should use descriptive variable names and appropriate levels of commenting (explain at a high-level the goal of different sections of code).

Page last updated: September 11, 2013