Implementing Timeouts in UDP
- 09 Kislev 5760 (18/11/1999)
Because UDP does not provide any reliabilty services for protocols
that are built on top of it,
such higher-level protocols have to implement reliability themselves.
For an example, see TFTP.
One type of reliability mechanism is called 'timeout'. When you wait
for a request/reply, you might be waiting forever. Thus, you'll
probably want to implement a timeout, so that after a certain amount
of time, you'll assume that you'll never get one.
In his book, UNIX Network Programming (volume 1: Networking APIs:
Sockets and XTI), W. Richard Stevens presents the following ways
to implement timeouts:
- select(2) function
- select is normally used when you are expecting I/O to/from more
than one file/socket. You tell it which file/socket descriptors
that you are waiting for, and it returns when I/O is ready on at
least one of them. But is also has a parameter specifying a
timeout; if that time expires before any I/O is ready,
select will also return.
Thus, when waiting for a request/reply on a socket, you can all
collect specifying only that socket, and a timeout.
- alarm(2) function
- You pass the alarm function a time. When that time is up, it will
generate an alarm signal (called SIGALRM). If the process is
blocked in a read/recv function call (that is, it called
the function, and it is waiting for input), then the alarm signal
will cause it to return.
There are 2 problems with this approach:
- exactly how signals are handled can differ between different
types of UNIX. Also, not all system call functions might be
interrupted by an alarm signal.
- If the program calls alarm in more than one place, the
different calls might interfere with each other.
- socket options: SO_RCVTIMEO and SO_SNDTIMEO
- These represent timeouts for reading/receiving (SO_RCVTIMEO) and
writing/sending (SO_SNDTIMEO). You set these options via the
setsockopt(2) function. Note that once you set them, they apply
to all subsequent read/recv (or write/send) calls.
The problem is that not all UNIX versions implement these options.
The goal of this document is to demonstrate all 3 approaches. The C
code consists of 3 layers:
- The top layer (the main function), which is common to all
approaches. This is the file
- The middle layer, which is different from each approach. In each
approach, I have the same function, 'receive_or_timeout'
with the same parameters, but the implementation is different.
This function is called by the top layer.
Currently, I have code only for one approach: using select. The
file is: via_select.c.
- The bottom layer, which is also common to all approaches. These
contain functions that are called by more than one of the
different versions of the 'receive_or_timeout' function. The
- socket_address.c -- converting
from strings to the sockaddr_in structure, and vice-versa.
- common.c -- other functions common to
more than one approach.
To see how to compile and link the program, here is the
Lab Instructor: Nachum Danzig
Wyler Building, rooms 232, Sun-Thur 13:30 - 14:30
Telephone at work: 02-675-1218