UDP Based Reliable Communication

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 5

UDP-based Reliable Communication

Gianni Perez
gianni.perez@protonmail.com

Department of Computer Science


Florida International University

control the flow of data to prevent overrunning the


Abstract - User Datagram Protocol (UDP) is a receiver with too many packets that it cannot process in
TCP/IP standard defined in RFC 768, "User due time. In my project, all of these factors have been
Datagram Protocol (UDP)." UDP is used by some carefully considered; however, providing all these
programs instead of TCP for fast, lightweight, features in a matter that is both efficient and scalable
unreliable transportation of data between TCP/IP has been a real challenge and only a portion of the
hosts. UDP provides a connectionless datagram characteristics of a protocol, such as TCP, have been
service that offers best-effort delivery, which means successfully carried out and implemented.
that UDP does not guarantee delivery or verify
sequencing for any packet delivered over a network.
This paper provides a comprehensive guide to a III. APPLICATION DESCRIPTION (CLASSES)
series of Java-written classes designed specifically
to attempt a reliable data transfer using UDP My application consists of the following Java classes:
datagram packets. rlbudp_client.java, which presents the user with a
console-based interface where he/she can enter the
parameters that prepare the client when initiating the
I. INTRODUCTION file transfer process. These parameters include: 1) the
Hostname or DNS name of the server that is to
become the file recipient. 2) the Port number to which
In general, differences in how UDP and TCP deliver
the server is listening at the remote location (this value
data are similar to the differences between a telephone
is set to “localhost” when a file needs to be copied onto
call and a postcard. TCP works like a telephone call by
the same machine. 3) the Filename of the file to be sent
verifying that the destination is available and ready to
including any extensions (necessary for binary-file
communicate. UDP works like a postcard --messages are
transfers). rlbudp_client.java takes the parameters entered
small and delivery is likely, but not always assured. UDP
by the user and passes them to UDPSender.java.
is typically used by programs that transmit small
UDPSender.java is the class in charge of the actual file
amounts of data at one time or have real-time
transfer process. In its basic form, it takes the server’s
requirements. In these situations, the low overhead and
hostname and port number and creates a
multicasting capabilities of UDP (for example, one
DatagramPacket that encapsulates specifically-sized
datagram, many recipients) are better suited than TCP.
bodies of file data to be transferred. The approach has
been to construct a header (see Section 5) consisting of
12 bytes to relay control information regarding the
II. CONCEPTS sending of sequence numbers and acknowledgements,
and a payload of a total of 512 bytes where the actual
To achieve reliable transmission by means of UDP file bytes are relayed. In total, UDPSender.java sends a
datagrams, several factors must be considered. For DatagramPacket of 524 bytes termed
example, the application-layer protocol must provide a DEFAULT_PKTSIZE in the class definition. This
way to ensure that data gets safely to its destination by class is also the main connection point with the remote
using techniques such as that of TCP. These include host and thus, it provides methods like
checking for lost or un-acknowledged packets, “checkHeader()” to receive information (e.g. acks) from
performing retransmissions whenever packets have not the server. It also provides a similar approach used by
been successfully acked, and providing methods that TCP called the “Three-Way Handshake” to initiate
connections as well as TCP’s close sequences to tear or differences depending on the role. Common to both
shut a connection down once the file transfer stage is these classes is the data member declaration: private
complete. All these connection stages are accomplished byte[] header = new byte[12]. This simply implies that both
by the use of Datagram Sockets; the main conduit to client and server use the same header size to transmit
send/receive UDP data using Java. control information such as flags and sequence
The next class called rlbudp_server.java, just as its numbers. In this same aspect, the method
counterpart rlbudp_client.java, provides the user with a makeHeader(byte[] header), which is in charge of building
console-based interface that accepts two basic a header is also employed by both main classes since
parameters: 1) the Port number to which the server information about sequence numbers and “acks” must
should be listening to. This port number is an integer be constantly exchanged between client and server.
that must be chosen in the range of 1025 to 65535 Perhaps the most important method in UDPReceiver.java
since ports 0-1024 are reserved by Unix/Linux systems is the one called getFileContent(). This method keeps the
and only accessible by the “root” user. 2) the Drop server open at all times for incoming packets; once a
Interval, which in the case of this project, it allows the packet is received, it checks its content by means of
user to imitate a noisy channel by making the server getPacketContent() and sets the timeout/drop interval
timeout with a frequency specified by the result of the rates according to what the user has entered. The
sequence number (of packet) modulo this drop interval mechanism works as follows: when a user enters a drop
given by: seqNum % dropInterval and specified in the interval at the command prompt other than zero(0), the
next class called UDPReceiver.java. method will take this value and perform a modulo
UDPReceiver.java is the main class in charge of getting operation with each sequence number being sent. If the
the server ready to start/end connections as well as remainder of this operation is zero (seqNum %
maintaining it while file transfers are in process. As dropInterval == 0), a timeout of exactly 3000 ms takes
previous classes, it relies on datagram packets and effect at the time a remainder of zero has been found.
sockets as means to communicate using UDP. This As explained before, this allows the user to simulate
class employs a buffer of 524 bytes large enough to be delays or simply a noisy channel.
able to accommodate packets (of the same size) coming There is also the method called startServer(int port),
from the client application. In the case of headers, which started initially as a way to provide multiple
where only 12 bytes are transferred at one time, the thread access to the server, in via of providing more
server makes adjustments to receive only this portion advanced features (e.g. packet re-ordering) but my first
of data without wasting array space. As the other main attempts did not work out as expected and I had to
class UDPSender.java, this class uses processes like the abandon the idea due to time restrictions. Other
“Three-Way Handshake” and relies on controls sent in methods like displayFile() are more simple in the sense
the packet’s header to effectively convey information to that they do not handle anything related to the
the remote client about the state of the transmission, communication/file-transfer process. displayFile() is in
including “acked” packets. place to let the user see a printout of the file that had
Some important methods in this class such as send() rely just been copied.
on information to be able to establish communication There are smaller yet important methods like
back to the client application. generateSeqNum(), which assists in the creation of
The next class called ByteBitSet.java provides both the random integers from 1 to 10 to be used in the header
main sender and receiver classes a mean to generate a for the purpose of establishing and terminating the
BitSet from a single byte. This allows for easy connection between client and server, as stated by the
manipulation of individual bits needed when “Three-Way Handshake” mechanism. The rest of the
setting/resetting flags in the reserved portion of the methods contain ample and clear comments that state
header. their purpose and functionalities throughout the overall
The last file is the interface called Sender, which framework of the program.
consists of single method called sendFile() used by
UDPSender.java to initiate the file transfer sequence.
V. THE HEADER

A great attempt has been made to simulate the relaying


of control information such as “acks” and sequence
numbers in the way the protocol TCP handles such
IV. APPLICATION DESCRIPTION (METHODS) task. The original idea was to employ separate string
objects to convey information back and forth from
Some of the most important methods are located in client to server, but I was soon encountered with some
both UDPReceiver.java and UDPSender.java. Being these problems. The most significant one was the fact that by
two classes the main contact point between client and employing separate packets to send “acks”, for example,
server, they contain data members and methods that an extra amount of traffic was going to be generated on
are common to each other with, of course, important the network and the possibility of packets not reaching
their destination was also likely to increase. This
resulted in the idea of creating an array of 12 bytes (as U A P R S F
requested in the project guidelines) paying particular RSVD
X X R C S S Y I
attention to things like sequence numbers and flag bits, (X)
G K H T N N
the most significant byte being the last byte of each
control. The following figure provides an overall view
on how the header was organized: Since now all the necessary information is packed into
one unit that travels along with the payload, no extra
0 31 packets are needed to maintain synchronization
Sequence Number between the sending and receiving side.

Acknowledgements
VI. THREE-WAY HANDSHAKE
Reserved Advertised Window
Following the same guidelines as TCP, I attempted to
The method makeHeader() in the main classes implement a method called the “three-way handshake”
UDPSender.java and UDPReceiver.java is represented to allow both client and server to exchange
below: synchronization signals prior to the file transfer stage
and after all the file had been copied. The following
private void makeHeader(byte[] header) graph illustrates how the application accomplishes this:
{
header[0] = (byte)((seqNum >>> 24) & 0xFF);
header[1] = (byte)((seqNum >>> 16) & 0xFF);
header[2] = (byte)((seqNum >>> 8) & 0xFF);
header[3] = (byte)(seqNum & 0xFF);
header[4] = (byte)((ack >>> 16) & 0xFF);
header[5] = (byte)((ack >>> 16) & 0xFF);
header[6] = (byte)((ack >>> 8) & 0xFF);
header[7] = (byte)(ack & 0xFF);
header[8] = (byte)((rsvd >>> 8) & 0xFF);
header[9] = (byte)(rsvd & 0x00);
header[10]= (byte)((windowSize >>> 8) &
0xFF);
header[11]= (byte)(windowSize & 0xFF);
}

This approach allowed me to manipulate bytes in the


header to encode information such as which flag is
set/cleared using methods like setAck(int control) below:

private void setAck(int control) throws IOException


{
if (control == 1)
header[9] |= 0x10; In this case, A is the sender (client) and B the receiver
if (control == 0) (server). A begins by sending the first packet with a
header[9] &= 0x00; sequence number value of 0 and the flag bit SYN set to
} 1. B, the server, responds with another packet and a
randomly-generated sequence number (1 to 10), setting
The following diagram shows a closeup of the reserved both the ACK and SYN flags in its header. The ack
byte dedicated to the flags. As the rest of the header, number that B sends to A is one more than the
the position of the flag bits resembles that of TCP. The sequence number previously sent by A, which in this
first part of the reserved space is not utilized (thus the case is equal to 1. Finally, A acknowledges B’s packet
X) and the first two bits of the 2nd reserved space are by adding 1 to B’s sequence number and setting the
also not utilized. ACK flag. Now, the file transfer stage may begin. The
following is an example output of this method as seen
0 7 15 in the console:

A- Sending side (Client)


VII. SLIDING WINDOW AND FLOW CONTROL

In an effort to prevent overflowing or overrunning the


server with too many incoming packets, I designed a
B- Receiving side (Server) vary basic sliding window scheme that can be
controlled according to how large the file being sent is.
Once a client establishes communication with the
server, the sending window size (sws) value at
UDPSender.java allows the client to send a specific
amount of packets (e.g. sws = 5) consecutively without
waiting for acknowlegments. After this window size
reaches zero, the client stops sending and waits for the
The connection closing process is similar; however, the
server to send back an acknowledgement for the 1st
server sends two consecutive packets setting the ACK
packet, then for the 2nd packet, and so forth. After an
and FIN flags independently. This is a sample screen of
acknowledgement is received, the window size
such event.
increases by one every time, and it exhibits this
behavior until the file transfer process is complete. In
A- Sending side (Client)
general terms, after the client sends n numbers of
packets consecutively, the application behaves like
1-bit-window sliding window protocol.

These are the steps:

Let sws = window size


B- Receiving side (Server) Sender can send up to sws packets without receiving
acknowledgment.

Packets are assigned sequence numbers 1,...,N-1 (sws


< N).

Sender sends sequence number with every packet.

And this is the figure that shows such process: Receiver acknowledges.

ACK i means all frames through i - 1 have been


received; ready to receive i.

This is a sample output of such event using a sender


window size value of 5:

The same process applies to the file transfer stage.


Every time a packet is received by the server, it takes An improved method for this sliding window
the sequence number and adds 1 to it, sending this new mechanism would be to provide dedicated, sending and
value in its “ack” field to the client, which lets the client receiving buffers to hold several numbers of packets at
know that a previous packet was correctly received. once without waiting to receive an acknowledgement
each time. Protocol or UDP. Part of this challenge lies on the fact
Since the window size is key to how the first part of the that multiple threads are needed to control the different
actual file transfer stage behaves, the following table processes happening at the same time as well as FIFO
suggests the window size according to the file size of queues that can manage the incoming and outgoing
the file being sent. packets in a manner that is both effective and
inexpensive in terms of time. The approach I have
followed attempts to do such thing but it falls short on
WINDOW SIZE SETTINGS other tasks. However, it leaves room for improvement
as the foundations for a reliable and efficient file
transfer mechanism have been carefully laid out on this
File Size * Window Size program.
** 524 to 1000 Bytes 1 or 2
1000 Bytes > 2+
1 MB > 10 – 15 (Recommended) Acknowledgments

* Making a window size of zero(0) is not allowed by the


program. Also, if a window size is made too large, there is Thanks to professor Chi Zhang at Florida International
still a risk that the receiver’s buffers might be overflowed.
** Sending a file less than 524 bytes will cause the program University School of Computer Science for his support
to abort since the packet size is set to this minimum on the and many recommendations on all the topics explored in
code itself. If the buffer size is decreased, smaller files can be
successfully copied over; however, some modification to the this report.
code will be needed to accomplish this.

VIII. OBSERVATIONS

During the initial stages of developing the program,


several issues were determined. As mentioned before,
without at least some kind of flow control mechanism,
the risk of overrunning the receiver with too much data
is very high, specially when sending large files. As a
matter of fact, at the early stage I noticed that small
files were being transferred without problems but large
files were sometimes cut in half as the server program
managed to keep up with the sending rate. This lead me
to build a simple Stop-And-Wait scheme that
acknowledged each packet at a time. This served as the
foundation to elaborate on a different approach using a
sliding window technique combined with this stop-and
wait scheme that works well for any type of file and any
file size. The timeouts or drop intervals implemented at
the server side allowed me to study how a noisy
channel may behave in real life. I placed a particular
emphasis in making sure the client would recover after
detecting such timeouts by looking for pending “acks”
sent previously by the server. By making this drop
interval 1, the application behaves almost exactly as a
pure Stop-And-Wait protocol because for every packet,
the server stops for a total of 3 seconds and the client is
forced to wait for each acknowledgement in the same
fashion as the Stop-And-Wait protocol.

IX. CONCLUSION

This project presented real challenges when designing a


© Copyright 2005 Gianni Perez
reliable way to transfer files using the User Datagram

You might also like