Setting the SO_REUSEADDR
Option
In the first part
of Chapter 11, “Concurrent
Client Servers” a server design using the fork(2) system call was presented
and tested. Figure 12.1 shows three processes that exist after a telnet command has
established contact with the server.
Figure 12.1:
This graphic illustrates the connection of
the telnet command to a forked server process.
The client is
being serviced by process ID 927. This means that you can kill process ID 926
and the client will continue to be serviced. However, no new connections to the
server can be made, because there will be no
server listening for new connections (listening server PID 926 was killed).
Now, if you were
to restart the server to listen for new connections, a problem would develop.
When the new server process attempts to bind the IP address 192.168.0.1 port
9099, the bind(2) function will
return the error EADDRINUSE. This error code indicates that the IP address is
already in use with port 9099. This occurs because process ID 927 is still
engaged in servicing a client. Address
192.168.0.1 port 9099 is still being used by that process (review Figure 12.1).
The solution to
this problem is to kill off process 927, which will close that socket and
release the IP address and port. However, if the client being serviced is the
CEO of the company you work for, this will not be an option (this might be a
career-limiting move). In the meantime, you'll be bugged by other departments,
wondering why you haven't restarted the server.
A better solution
to the problem just presented is to use the SO_REUSEADDR socket option. All servers
should make use of this option, unless there is a good reason not to. To make
effective use of this option, perform the following in the server, which
listens for connections:
- Create your listening socket as usual with socket(2).
- Call setsockopt(2) setting SO_REUSEADDR option to TRUE.
- Now call bind(2) as usual.
The socket will
now be marked as reusable. If the listening server process (PID 926 in Figure
12.1) terminates for any reason, you will be able to be restart it. This will
be true even when a client has another server
process engaged using the same IP address and port number.
In order for SO_REUSEADDR
option to be effective, the following conditions must be met:
- No other socket with the same IP address and port can be in a listen mode.
- All sockets with the same IP address and port number must have the SO_REUSEADDR option set to TRUE.
What this means
is that there can be only one listener at a specific IP address and port number
pair. If one such socket already exists, then setting the option will not
accomplish your goal. Setting SO_REUSEADDR to TRUE can be effective only if all
existing sockets with the same address and port number have this option set. If
any existing socket does not have this option set, then bind (2) will continue
to return an error.
The following code shows how to set the option to TRUE:
Example
#define TRUE 1
#define FALSE 0
int z; /* Status code */
int s; /* Socket number */
int so_reuseaddr
= TRUE;
z = setsockopt(s,
SOL_SOCKET,
SO_REUSEADDR,
&so_reuseaddr,
sizeof so_reuseaddr);
The SO_REUSEADDR option
can be queried with the getsockopt(2) function if required.
See Also
SO_PASSCRED & SO_PEERCRED, SO_BROADCAST, SO_KEEPALIVE, SO_LINGER, SO_OBINLINE, SO_TYPE
No comments:
Post a Comment