Unix Network Programming Manual
Timers
In many situations in network programming
Essential to the use of signals and asynchronous I/O, as well as to normal
protocol management are timers. Operating systems provide utilities that
allow a programmer to keep track of time in a number of ways, using the
internal computer clocks. By using these clocks, a programmer can arrange
to have a signal sent to the process when a particular amount of time
has elapsed, or when a particular relative time has been reached.
For example, when you do something like a broadcast for servers, the
responses are asynchronous - not specifically organized in time. That
means that some servers might respond very quickly, while other take
longer, either because the host is busy or because they are simply slower.
When the broadcast is sent, your program needs to give a
reasonable amount of time for the servers to respond, and then not wait any
longer. If some server takes 5 minutes to respond, you probably don't want
it doing work for you anyway. Therefore, you need to set up a timer
that will let you terminate the query-for-server process at a reasonable
time.
Another example is receive request that may not return because the other
end has terminated or made a protocol error. It is reasonable to limit
the wait time by starting a timer and when it expires, halt the receive
process and cleanup this particular communication channel.
The following code implements an alarm timer, which is a timer that
signals the process after the passage of a certain amount of time.
/* ==================================================================>
*
* Example of setting up a unix timer. The setitimer call starts a
* timer running and when it expires, it generates a signal. The
* process is to set up a signal handler for the particular timer
* being used, which is the alarm timer in this case, and then
* use setitimer to get the alarm clock started. When it expires,
* the signal handler gets called.
*
* ======================================================================
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <signal.h>
void AlarmHandler ();
void main ()
{
struct itimerval itimer;
int interval = 5; /* 5 second interval */
/*
* Set up a signal handler for the SIGALRM signal which is what the
* expiring timer will set.
*/
signal (SIGALRM, AlarmHandler);
/*
* Set the timer up to be non repeating, so that once it expires, it
* doesn't start another cycle. What you do depends on what you need
* in a particular application.
*/
itimer . it_interval . tv_sec = 0;
itimer . it_interval . tv_usec = 0;
/*
* Set the time to expiration to interval seconds.
* The timer resolution is milliseconds.
*/
itimer . it_value . tv_sec = interval;
itimer . it_value . tv_usec = 0;
if (setitimer (ITIMER_REAL, &itimer, NULL) < 0)
{
perror ("StartTimer could not setitimer");
exit (0);
}
/*
* Hang around and wait until something happens. The pause command
* causes a program to suspend execution until an event occurs. In
* this case, the event will be the timer expiration, which will cause
* the signal handler to be executed and upon return, the pause will
* be complete and the program will terminate.
*/
printf ("The timer has started\n");
pause ();
/*
* Note that if conditions indicate that you don't want to wait for
* a timer to expire. For example, if in a sliding window protocol
* you get the ACK for a message, you can kill the alarm by calling
* setitimer and setting the interval value to 0.
*/
}
void AlarmHandler ()
{
printf ("The 5 seconds has expired\n");
return;
}
The itimerval structure has two parts. The it_value part indicates how
long you want to wait for the first signal. The it_interval part
indicates how often you want it to occur after that. In this case, the
timer interrupt is to occur once, so the interval is set to zero.
In the following pages, examples of timers will be used in discussing
various kinds of asynchronous I/O. However, the following functions are
typical of the routines that you might set up in a program to ease the
management of functions.
/* ==========================================================> StartTimer
*
* int StartTimer (int interval)
*
* Set a real time timer to expire in interval seconds and return
* zero for successful or negative for error.
*
* =====================================================================
*/
int StartTimer
(
int interval
)
{
struct itimerval itimer;
/*
* Set the timer up to be non repeating.
*/
itimer . it_interval . tv_sec = 0;
itimer . it_interval . tv_usec = 0;
/*
* Set the time to expiration to interval seconds.
* The timer resolution is milliseconds.
*/
itimer . it_value . tv_sec = interval;
itimer . it_value . tv_usec = 0;
if (setitimer (ITIMER_REAL, &itimer, NULL) < 0)
{
perror ("StartTimer could not setitimer");
return (-1);
}
return (0);
}
/* ==========================================================> StopTimer
*
* int StopTimer (int interval)
*
* Set a real time timer to expire in interval seconds and return
* zero for successful or negative for error.
*
* Not actually used int this program.
*
* =====================================================================
*/
int StopTimer ()
{
struct itimerval itimer;
/*
* Set the timer up to be non repeating and a timeout of zero.
*/
itimer . it_interval . tv_sec = 0;
itimer . it_interval . tv_usec = 0;
itimer . it_value . tv_sec = 0;
itimer . it_value . tv_usec = 0;
if (setitimer (ITIMER_REAL, &itimer, NULL) < 0)
{
perror ("StopTimer could not setitimer");
return (-1);
}
return (0);
}