Linux Socket Programming by Example - Warren Gay

< BACKCONTINUE >
159231153036212041242100244042145096184016146223183074028121223008110134181079170140090066062

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.
graphics/12fig01.gif

The steps that take place in Figure 12.1 are as follows:

  1. The server process (PID 926) is started. It listens for connections from clients.

  2. The client process (a telnet command) is started, and connects to the server process (PID 926).

  3. The server process (PID 926) forks by calling fork(2). This leaves the original parent process (PID 926) and a new server child process (PID 927).

  4. The connected client socket is closed by the parent server process (PID 926), leaving the connected client socket open only in the child process (PID 927).

  5. The telnet command and the child server process (PID 927) converse at will, independently of the parent process (PID 926).

At step 5, there are two socket activities happening:

  • The server (PID 926) is listening on 192.168.0.1 port 9099.

  • The client is being served by the socket 192.168.0.1 port 9099 (by PID 927), which is connected to the client's address of 192.168.0.2 port 1035.

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:

  1. Create your listening socket as usual with socket(2).

  2. Call setsockopt(2) setting SO_REUSEADDR option to TRUE.

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

					
#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.

< BACKCONTINUE >

Index terms contained in this section

commands
     telnet
            server connections 2nd
connections
     server
            SO_REUSEADDR socket option 2nd
            telnet commands 2nd
reusing sockets
      setting SO_REUSEADDR socket option 2nd
servers
     connections
            SO_REUSEADDR socket option 2nd
            telnet command 2nd
setting
     socket options
            SO_REUSEADDR 2nd
SO_REUSEADDR socket option
      setting 2nd
sockets
     options
            SO_REUSEADDR 2nd
telnet command
      server connections 2nd