Sockets have options that control various aspects of their operation. Among the things you can adjust are the sizes of the buffers used to send and receive data, the values of send and receive timeouts, and whether the socket can be used to receive broadcast transmissions. The default options are fine for most purposes; however, occasionally you may want to adjust some options to optimize your application, or to enable optional features of the TCP/IP protocol. The most commonly used option is SO_REUSEADDR , which is frequently activated in server applications. Socket options can be examined or changed with the Perl built-in functions getsockopt() and setsockopt() . $value = getsockopt (SOCK,$level,$option_name); $boolean = setsockopt (SOCK,$level,$option_name,$option_value); The getsockopt() and setsockopt() functions allow you to examine and change a socket's options. The first argument is the filehandle for a previously created socket. The second argument, $level , indicates the level of the networking stack you wish to operate on. You will usually use the constant SO_SOCKET , indicating that you are operating on the socket itself. However, a getsockopt() and setsockopt() are occasionally used to adjust options in the TCP or UDP protocols, in which case you use the protocol number returned by getprotobyname () . The third argument, $option_name, is an integer value selected from a large list of possible constants. The last argument, $option_value , is the value to set the option to, or it returns undef if inapplicable. On success, getsockopt() returns the value of the requested option, or undef if the call failed. On success, setsockopt() returns a true value if the option was successfully set; otherwise , it returns undef . | The value of an option is often a Boolean flag indicating whether the option should be turned on and off. In this case, no special code is needed to set or examine the value. For example, here is how to set the value of SO_BROADCAST to true (broadcasting is discussed in Chapter 20): setsockopt(SOCK,SO_SOCKET,SO_BROADCAST,1); And here is how to retrieve the current value of the flag: my $reuse = getsockopt(SOCK,SO_SOCKET,SO_BROADCAST); However, a few options act on integers or more esoteric data types, such as C timeval structures. In this case, you must pack the values into binary form before passing them to setsockopt() and unpack them after calling getsockopt() . To illustrate , here is the way to recover the maximum size of the buffer that a socket uses to store outgoing data. The SO_SNDBUF option acts on a packed integer (the "I" format): $send_buffer_size = unpack("I",getsockopt($sock,SOL_SOCKET,SO_SNDBUF)); Common Socket Options Table 4.2 lists the common socket options used in network programming. These constants are imported by default when you load the Socket module. SO_REUSEADDR allows a TCP socket to rebind to a local address that is in use. It takes a Boolean argument indicating whether to activate address reuse. See the section The SO_REUSEADDR Socket Option later in this chapter. SO_KEEPALIVE, when set to a true value, tells a connected socket to send messages to the peer intermittently. If the remote host fails to respond to a message, your process will receive a PIPE signal the next time it tries to write to the socket. The interval of the keepalive messages cannot be changed in a portable way and varies from OS to OS (it is 45 seconds on my Linux system). SO_LINGER controls what happens when you try to close a TCP socket that still has unsent queued data. Normally, close() returns immediately, and the operating system continues to try to send the unsent data in the background. If you prefer, you can make the close() call block until all the data has been sent by setting SO_LINGER , allowing you to inspect the return value returned by close() for successful completion. Unlike other socket options, SO_LINGER operates on a packed data type known as the linger structure. The linger structure consists of two integers: a flag indicating whether SO_LINGER should be active, and a timeout value indicating the maximum number of seconds that close() should linger before returning. The linger structure should be packed and unpacked using the II format: $linger = pack("II",$flag,$timeout); For example, to make a socket linger for up to 120 seconds you would call: setsockopt(SOCK,SOL_SOCKET, SO_LINGER,pack("II",1,120)) or die "Can't set SO_LINGER: $!"; SO_BROADCAST is valid for UDP sockets only. If set to a true value, it allows send() to be used to send packets to the broadcast address for delivery to all hosts on the local subnet. We discuss broadcasting in Chapter 20. The SO_OOBINLINE flag controls how out-of- band information is handled. This feature allows the peer to be alerted of the presence of high-priority data. We describe how this works in Chapter 17. SO-SNDLOWAT and SO_RCVLOWAT set the low-water marks for the output and input buffers, respectively. The significance of these options is discussed in Chapter 13, Nonblocking I/O. These options are integers, and must be packed and unpacked using the I pack format. SO_TYPE is a read-only option. It returns the type of the socket, such as SOCK_STREAM . You will need to unpack this value with the I format before using it. The IO::Socket sockopt() method discussed in Chapter 5 does the conversion automatically. Table 4.2. Common Socket Options Option | Description | SO_REUSEADDR | Enable reuse of the local address. | SO_KEEPALIVE | Enable the transmission of periodic "keepalive" messages. | SO_LINGER | Linger on close if data present. | SO_BROADCAST | Allow socket to send messages to the broadcast address. | SO_OOBINLINE | Keep out-of-band data inline. | SO_SNDLOWAT | Get or set the size of the output buffer "low water mark." | SO_RECVLOWAT | Get or set the size of the input buffer "low water mark." | SO_TYPE | Get the socket type (read only). | SO_ERROR | Get and clear the last error on the socket (read only). | Last, the read-only SO_ERROR option returns the error code, if any, for the last operation on the socket. It is used for certain asynchronous operations, such as nonblocking connects (Chapter 13). The error is cleared after it is read. As before, users of getsockopt() need to unpack the value with the I format before using it, but this is taken care of automatically by IO::Socket. The SO_REUSEADDR Socket Option Many developers will want to activate the SO_REUSEADDR flag in server applications. This flags allows a server to rebind to an address that is already in use, allowing the server to restart immediately after it has crashed or been killed . Without this option, the bind() call will fail until all old connections have timed out, a process that may take several minutes. The idiom is to insert the following line of code after the call to socket() and before the call to bind() : setsockopt(SOCK,SOL_SOCKET,SO_REUSEADDR,1) o r die "setsockopt: $!"; The downside of setting SO_REUSEADDR is that it allows you to launch your server twice. Both processes will be able to bind to the same address without triggering an error, and they will then compete for incoming connections, leading to confusing results. Servers that we develop later (e.g., Chapters 10, 14, and 16) avoid this possibility by creating a file when the program starts up and deleting it on exit. The server refuses to launch if it sees that this file already exists. The operating system does not allow a socket address bound by one user's process to be bound by another user 's process, regardless of the setting of SO_REUSEADDR . The fcntl() and ioctl() Functions In addition to socket options, a number of attributes are adjusted using the fcntl() and ioctl() functions. We discuss fcntl() in Chapter 13, where we use it to turn on nonblocking I/O, and again in Chapter 17, where we use fcntl() to set the owner of a socket so that we receive a URG signal when the socket receives TCP urgent data. The ioctl() function appears in Chapter 17 as well, where we use it to implement the sockatmark() function for handling urgent data, and again in Chapter 21, where we create a variety of functions for examining and modifying the IP addresses assigned to network interfaces. |