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:

  1. 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.
  2. 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:

  1. The top layer (the main function), which is common to all approaches. This is the file udp_timeout.c.
  2. 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.

  3. 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 files are:

To see how to compile and link the program, here is the Makefile.

Lab Instructor: Nachum Danzig
Wyler Building, rooms 232, Sun-Thur 13:30 - 14:30
Telephone at work: 02-675-1218