Example 3

[ Back to Software Project Homepage ]


Introduction

In this example, the sender sends 1 packet on an unreliable duplex link.
The forward and reverse path of this link both has 50% packet drop probability and 1 second link delay.

Because it is difficult to have this kind of link in reality, I simulate this with a new class "LossyReceivingPort". This port will drop the packets randomly on a pre-defined ratio. Also, whenever the port receives a packet, an artificial 1-second delay is introduced.

Actually, this 1-second is not a real link delay constraint , but more like a link bandwidth constraint. This link would be more approriate to be understood as a "link whose bandwidth is limited to (packet_size*8) bits/second with zero propagation delay."

As the link is unreliable, packets might need to be retransmitted.
The main purpose of this example is to show how a sending port handle this with the help of a timer.

Timer

TxTimer class is designed for a timing control purpose for a sending port. The timer is used to  schedule a later event/transmission occured in a port.  The timer is associated with a SendingPort object. It runs as a separate Linux thread once started. When the timer expires, the SendingPort::timerHandler() will be called.

As the timerHandler() function is virtual in the base class, a child class has to be deirved from the SendingPort class. And you could design your own timerHandler() in this child class.

Source Code can be found in the package.

Code Analysis:

Derive a sending port class

In newoport.h, I created a customized sending port class. Note that there is no newport.cpp because all functions are declared as "inline". You can also create a separate cpp file if you want.

Setting up the duplex link:

The codes to configure the link are shown below:

sender.cpp
receiver.cpp
 const char* hname = "localhost";       
Address * my_tx_addr = new Address(hname, 3000);

//configure sending port
Address * dst_addr = new Address(argv[1], (short)(atoi(argv[2])));
mySendingPort *my_port = new mySendingPort();
my_port->setAddress(my_tx_addr);
my_port->setRemoteAddress(dst_addr);
my_port->init();

//configure receiving port to listen to ACK frames
Address * my_rx_addr = new Address(hname, (short)(atoi(argv[3])));
LossyReceivingPort *my_rx_port = new LossyReceivingPort(0.5);
my_rx_port->setAddress(my_rx_addr);
my_rx_port->init();

 const char* hname = "localhost";  

//configure receiving port
Address * my_addr = new Address(hname, (short)(atoi(argv[1])));

LossyReceivingPort *my_port = new LossyReceivingPort(0.5);
my_port->setAddress(my_addr);
my_port->init();

//configure a sending port to send ACK
Address * my_tx_addr = new Address(hname, 3005);
Address * dst_addr = new Address(argv[2], (short)(atoi(argv[3])));
mySendingPort *my_tx_port = new mySendingPort();
my_tx_port->setAddress(my_tx_addr);
my_tx_port->setRemoteAddress(dst_addr);
my_tx_port->init();

Look at the code:
LossyReceivingPort *my_port = new LossyReceivingPort(0.5);
This creates a RX port to drop half of the incoming packets randomly. Both sender and receiver have a sending port and receiving port.
The duplex link is shown as below:
gif

Note that the sender is "Node 1" and the receiver is "Node 2". If the program is going to be tested in one computer, the rx_port of sender and receiver have to be different because each port can be only bind to a single program.

Control the retransmission

The code:
my_port->timer_.startTimer(2.5);
scheduled the sending port's timer to expire 2.5 seconds later. If the timer expires and the ACK packet is not received,  the timerHandler() of this port will re-send the last packet.

Compile and Test the program

make
./receiver 5001 localhost 5000

./sender localhost 5001 5000

packet is first sent!
begin waiting for ACK...
The last sent packet has not been acknowledged yet. Re-send...
The last sent packet has not been acknowledged yet. Re-send...
The last sent packet has not been acknowledged yet. Re-send...
The last sent packet has not been acknowledged yet. Re-send...
The last sent packet has been acknowledged.