Team BBL
Previous Page Next Page

16.6. Socket Options

The 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:

  1. Generic options that work with all socket types

  2. Options that are managed at the socket level, but depend on the underlying protocols for support

  3. Protocol-specific options unique to each individual protocol

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.

#include <sys/socket.h>

int setsockopt(int sockfd, int level, int option,
 const void *val,
               socklen_t len);

Returns: 0 if OK, 1 on error


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.

Figure 16.19. Socket options

Option

Type of val argument

Description

SO_ACCEPTCONN

int

Return whether a socket is enabled for listening (getsockopt only).

SO_BROADCAST

int

Broadcast datagrams if *val is nonzero.

SO_DEBUG

int

Debugging in network drivers enabled if *val is nonzero.

SO_DONTROUTE

int

Bypass normal routing if *val is nonzero.

SO_ERROR

int

Return and clear pending socket error (getsockopt only).

SO_KEEPALIVE

int

Periodic keep-alive messages enabled if *val is nonzero.

SO_LINGER

struct linger

Delay time when unsent messages exist and socket is closed.

SO_OOBINLINE

int

Out-of-band data placed inline with normal data if *val is nonzero.

SO_RCVBUF

int

The size in bytes of the receive buffer.

SO_RCVLOWAT

int

The minimum amount of data in bytes to return on a receive call.

SO_RCVTIMEO

struct timeval

The timeout value for a socket receive call.

SO_REUSEADDR

int

Reuse addresses in bind if *val is nonzero.

SO_SNDBUF

int

The size in bytes of the send buffer.

SO_SNDLOWAT

int

The minimum amount of data in bytes to transmit in a send call.

SO_SNDTIMEO

struct timeval

The timeout value for a socket send call.

SO_TYPE

int

Identify the socket type (getsockopt only).


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.

#include <sys/socket.h>

int getsockopt(int sockfd, int level, int option,
 void *restrict val,
               socklen_t *restrict lenp);

Returns: 0 if OK, 1 on error


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.

Example

The 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);
}

    Team BBL
    Previous Page Next Page