The Linux Programming Interface

(nextflipdebug5) #1
Sockets: Advanced Topics 1279

The optname argument identifies the option whose value we wish to set or
retrieve. The optval argument is a pointer to a buffer used to specify or return the
option value; this argument is a pointer to an integer or a structure, depending on
the option.
The optlen argument specifies the size (in bytes) of the buffer pointed to by
optval. For setsockopt(), this argument is passed by value. For getsockopt(), optlen is a
value-result argument. Before the call, we initialize it to the size of the buffer
pointed to by optval; upon return, it is set to the number of bytes actually written to
that buffer.
As detailed in Section 61.11, the socket file descriptor returned by a call to
accept() inherits the values of settable socket options from the listening socket.
Socket options are associated with an open file description (refer to Figure 5-2,
on page 95). This means that file descriptors duplicated as a consequence of dup()
(or similar) or fork() share the same set of socket options.
A simple example of a socket option is SO_TYPE, which can be used to find out
the type of a socket, as follows:

int optval;
socklen_t optlen;

optlen = sizeof(optval);
if (getsockopt(sfd, SOL_SOCKET, SO_TYPE, &optval, &optlen) == -1)
errExit("getsockopt");

After this call, optval contains the socket type—for example, SOCK_STREAM or
SOCK_DGRAM. Using this call can be useful in a program that inherited a socket file
descriptor across an exec()—for example, a program execed by inetd—since that pro-
gram may not know which type of socket it inherited.
SO_TYPE is an example of a read-only socket option. It is not possible to use
setsockopt() to change a socket’s type.

61.10 The SO_REUSEADDR Socket Option


The SO_REUSEADDR socket option serves a number of purposes (see Chapter 7 of
[Stevens et al., 2004] for details). We’ll concern ourselves with only one common
use: to avoid the EADDRINUSE (“Address already in use”) error when a TCP server is
restarted and tries to bind a socket to a port that currently has an associated TCP.
There are two scenarios in which this usually occurs:

z A previous invocation of the server that was connected to a client performed
an active close, either by calling close(), or by crashing (e.g., it was killed by a signal).
This leaves a TCP endpoint that remains in the TIME_WAIT state until the
2MSL timeout expires.
z A previous invocation of the server created a child process to handle a connec-
tion to a client. Later, the server terminated, while the child continues to serve
the client, and thus maintain a TCP endpoint using the server’s well-known port.
Free download pdf