Sockets

setsockopt#

Set a kernel-level option on an open socket.

setsockopt is the Perl wrapper around the POSIX setsockopt(2) system call. It writes the option named by OPTNAME at protocol LEVEL on the already-opened SOCKET filehandle, using the value packed into OPTVAL. It is the knob for everything the kernel lets you tune on a socket — address reuse, keepalives, timeouts, Nagle’s algorithm, multicast membership, send and receive buffer sizes, SO_LINGER behaviour on close, and so on. Symbolic names for LEVEL and OPTNAME come from the Socket module.

Synopsis#

setsockopt SOCKET, LEVEL, OPTNAME, OPTVAL

What you get back#

A true value on success, undef on failure (with $! set to the underlying errno: EBADF, ENOPROTOOPT, EINVAL, ENOTSOCK, etc.). Always check the return value — a silently-ignored option means the program runs with defaults that differ from what the code reads:

setsockopt($sock, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))
    or die "setsockopt SO_REUSEADDR: $!";

Global state it touches#

None directly. setsockopt sets $! on failure; that is the only interpreter global involved. The effect is on the kernel-side state of the socket, not on any Perl-level variable.

OPTVAL — packed bytes or a bare integer#

Most socket options take a C int flag. setsockopt accepts either form for convenience:

  • A packed byte string whose layout matches the option’s C type, typically built with pack: pack("l", 1) for a boolean, pack("ll", $on_secs, $on_usecs) for a struct timeval, pack("ii", $on, $linger) for struct linger.

  • A plain integer, which is shorthand for pack("i", OPTVAL). Handy for SO_REUSEADDR, TCP_NODELAY, and other boolean flags:

    setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, 1);
    

Options whose value is a struct (SO_LINGER, SO_RCVTIMEO, IP_ADD_MEMBERSHIP) must be passed as an explicit packed string. A bare integer there produces EINVAL or, worse, silently writes wrong-sized memory that the kernel misinterprets.

Examples#

Disable Nagle’s algorithm on a TCP socket so small writes go out immediately — useful for latency-sensitive protocols (interactive shells, game traffic, RPC):

use Socket qw(IPPROTO_TCP TCP_NODELAY);

setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, 1)
    or die "TCP_NODELAY: $!";

Allow a server to rebind a port that is still in TIME_WAIT from a previous process — the single most common setsockopt call in practice, and it must come before bind:

use Socket qw(SOL_SOCKET SO_REUSEADDR);

setsockopt($srv, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))
    or die "SO_REUSEADDR: $!";
bind($srv, sockaddr_in(9000, INADDR_ANY))
    or die "bind: $!";

Set a receive timeout so a blocking recv or read from the socket returns with EAGAIN / EWOULDBLOCK after 5 seconds instead of hanging forever. The option value is a packed struct timeval:

use Socket qw(SOL_SOCKET SO_RCVTIMEO);

my $tv = pack("l!l!", 5, 0);    # 5 seconds, 0 microseconds
setsockopt($sock, SOL_SOCKET, SO_RCVTIMEO, $tv)
    or die "SO_RCVTIMEO: $!";

Enable TCP keepalive probes so half-open connections (peer crashed, cable yanked) are eventually noticed and the socket errors out rather than blocking indefinitely:

use Socket qw(SOL_SOCKET SO_KEEPALIVE);

setsockopt($sock, SOL_SOCKET, SO_KEEPALIVE, 1)
    or die "SO_KEEPALIVE: $!";

Make close block for up to 10 seconds while the kernel flushes unsent data, then discard and reset. SO_LINGER takes a two-integer struct: the on-flag and the timeout in seconds:

use Socket qw(SOL_SOCKET SO_LINGER);

setsockopt($sock, SOL_SOCKET, SO_LINGER, pack("ii", 1, 10))
    or die "SO_LINGER: $!";

Enlarge the kernel receive buffer for a bulk-transfer socket. The kernel typically doubles the value you request and caps it at net.core.rmem_max:

use Socket qw(SOL_SOCKET SO_RCVBUF);

setsockopt($sock, SOL_SOCKET, SO_RCVBUF, 1 << 20)   # 1 MiB
    or die "SO_RCVBUF: $!";

Edge cases#

  • SOCKET must already be open. setsockopt does not create the socket — call socket first. A closed or never-opened filehandle fails with EBADF.

  • Ordering matters. SO_REUSEADDR must be set before bind. SO_KEEPALIVE can go before or after connect, but for server sockets set it on the accepted child filehandle returned by accept, not on the listening one — options do not always propagate.

  • Integer shorthand is pack("i", N), not pack("l", N). On platforms where int and long differ in size, passing a plain integer and passing pack("l", N) write different byte counts. Both happen to work for the common int-sized boolean options on LP64 Linux, but the shorthand form is the portable default.

  • Struct-valued options need explicit pack. SO_LINGER, SO_RCVTIMEO, SO_SNDTIMEO, IP_ADD_MEMBERSHIP, IP_MREQ, and similar take fixed-layout structs. Pass a packed string of the right length or the kernel rejects the call with EINVAL.

  • LEVEL picks the option namespace. SOL_SOCKET for generic options, IPPROTO_TCP for TCP-specific (TCP_NODELAY, TCP_KEEPIDLE), IPPROTO_IP for IPv4 (IP_TTL, IP_ADD_MEMBERSHIP), IPPROTO_IPV6 for IPv6. Mismatching LEVEL and OPTNAME gives ENOPROTOOPT.

  • Read-only or unsupported options fail with ENOPROTOOPT. This also fires when the kernel simply does not know the option — common when copying code between operating systems.

  • Privileged options. A few options (SO_PRIORITY above certain values, IP_TRANSPARENT, SO_BINDTODEVICE) require CAP_NET_ADMIN on Linux; an unprivileged call fails with EPERM.

  • Reading back is getsockopt, not setsockopt. setsockopt has no query form; use getsockopt to confirm what the kernel actually stored (it may round, clamp, or double the value).

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • getsockopt — the query counterpart; read back an option to see what the kernel actually applied

  • socket — create the socket filehandle that setsockopt configures; must be called first

  • bind — set SO_REUSEADDR with setsockopt before calling bind on a server socket

  • accept — options set on the listener do not all propagate; re-apply per-connection options on the accepted handle

  • pack — builds the OPTVAL byte string for struct-valued options like SO_LINGER and SO_RCVTIMEO

  • Socket — source of SOL_SOCKET, IPPROTO_TCP, SO_REUSEADDR, TCP_NODELAY, and the rest of the symbolic constants