16.6. Socket OptionsThe socket mechanism provides two socket-option interfaces for us to control the behavior of sockets. One interface is used to set an option, and another interface allows us to query the state of an option. We can get and set three kinds of options:
The Single UNIX Specification defines only the socket-layer options (the first two option types in the preceding list). We can set a socket option with the setsockopt function.
The level argument identifies the protocol to which the option applies. If the option is a generic socket-level option, then level is set to SOL_SOCKET. Otherwise, level is set to the number of the protocol that controls the option. Examples are IPPROTO_TCP for TCP options and IPPROTO_IP for IP options. Figure 16.19 summarizes the generic socket-level options defined by the Single UNIX Specification.
The val argument points to a data structure or an integer, depending on the option. Some options are on/off switches. If the integer is nonzero, then the option is enabled. If the integer is zero, then the option is disabled. The len argument specifies the size of the object to which val points. We can find out the current value of an option with the getsockopt function.
Note that the lenp argument is a pointer to an integer. Before calling getsockopt, we set the integer to the size of the buffer where the option is to be copied. If the actual size of the option is greater than this size, the option is silently truncated. If the actual size of the option is less than or equal to this size, then the integer is updated with the actual size on return. ExampleThe function in Figure 16.10 fails to operate properly when the server terminates and we try to restart it immediately. Normally, the implementation of TCP will prevent us from binding the same address until a timeout expires, which is usually on the order of several minutes. Luckily, the SO_REUSEADDR socket option allows us to bypass this restriction, as illustrated in Figure 16.20. To enable the SO_REUSEADDR option, we set an integer to a nonzero value and pass the address of the integer as the val argument to setsockopt. We set the len argument to the size of an integer to indicate the size of the object to which val points. Figure 16.20. Initialize a socket endpoint for use by a server with address reuse#include "apue.h" #include <errno.h> #include <sys/socket.h> int initserver(int type, const struct sockaddr *addr, socklen_t alen, int qlen) { int fd, err; int reuse = 1; if ((fd = socket(addr->sa_family, type, 0)) < 0) return(-1); if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0) { err = errno; goto errout; } if (bind(fd, addr, alen) < 0) { err = errno; goto errout; } if (type == SOCK_STREAM || type == SOCK_SEQPACKET) { if (listen(fd, qlen) < 0) { err = errno; goto errout; } } return(fd); errout: close(fd); errno = err; return(-1); } |