listen#
Mark a socket as passive so it can accept incoming connections.
listen is the third step in the classic server setup — after socket creates the endpoint and bind fixes it to a local address, listen switches it into the listening state and sizes the kernel’s backlog queue of pending connections. Incoming connections are then drained one at a time with accept. QUEUESIZE is the maximum number of connections the kernel will hold for you before it starts refusing new ones.
Synopsis#
listen SOCKET, QUEUESIZE
What you get back#
True on success, false on failure (with $! set to the errno from the underlying listen(2)). Always check the return value — a server that silently fails to enter the listening state will accept no connections, and the cause (a stale socket file, a port collision, an unbound descriptor) is only visible through $!.
listen $srv, SOMAXCONN
or die "listen on $path: $!";
Global state it touches#
listen reads no special variables and writes only $! on failure. The call is a thin wrapper over the kernel’s listen(2); effects are on the socket descriptor, not on Perl state.
Examples#
A minimal TCP server. socket, bind, listen, accept in order — miss any step and accept fails:
use Socket;
socket(my $srv, PF_INET, SOCK_STREAM, getprotobyname("tcp"))
or die "socket: $!";
setsockopt($srv, SOL_SOCKET, SO_REUSEADDR, 1)
or die "setsockopt: $!";
bind($srv, sockaddr_in(8080, INADDR_ANY))
or die "bind: $!";
listen($srv, SOMAXCONN)
or die "listen: $!";
while (accept(my $cli, $srv)) {
# serve $cli ...
close $cli;
}
A Unix-domain server. Same sequence, different address family:
use Socket;
my $path = "/tmp/myservice.sock";
unlink $path; # stale socket file would cause EADDRINUSE
socket(my $srv, PF_UNIX, SOCK_STREAM, 0) or die "socket: $!";
bind($srv, sockaddr_un($path)) or die "bind: $!";
listen($srv, 16) or die "listen: $!";
Using the POSIX-defined cap SOMAXCONN rather than hard-coding a number. The kernel silently clamps larger values to its own limit anyway; SOMAXCONN documents intent:
use Socket qw(SOMAXCONN);
listen($srv, SOMAXCONN) or die "listen: $!";
A small backlog for a service that processes connections faster than they arrive:
listen($srv, 5) or die "listen: $!";
Re-listening on an already-listening socket. A second call with a different QUEUESIZE is legal on Linux and resizes the backlog in place:
listen($srv, 128) or die "listen: $!";
# ... later, under load:
listen($srv, 1024) or die "listen: $!"; # grow the queue
Edge cases#
Call order matters. Calling
listenon a socket that has not beenbind-ed fails withEDESTADDRREQ(or on some kernels an autobound ephemeral port — do not rely on that). Callingacceptbeforelistenfails withEINVAL.Only for connection-oriented sockets.
listenis meaningful onSOCK_STREAMandSOCK_SEQPACKET. Calling it on aSOCK_DGRAMsocket fails withEOPNOTSUPP; UDP has no notion of pending connections.QUEUESIZEis advisory. The kernel clamps it to/proc/sys/net/core/somaxconn(Linux) regardless of what you ask for. A value of0is accepted but means “rely on kernel-default backlog”; it does not disable listening.Negative values are silently treated as
0by the kernel. Perl does not diagnose this — check your input before passing it tolisten.EADDRINUSEatlistenvs atbind. Port conflicts for TCP/UDP surface atbind;listenrarely fails with this. For Unix-domain sockets a leftover socket file from a previous run causesbindto fail withEADDRINUSE— remove it withunlinkbefore binding.Stale connections in the queue. When
acceptruns, the returned connection may already be closed by the peer (the client gave up while queued). Handle that like any other I/O error from the new socket, not as alistenproblem.After
fork. A listening socket inherited by a child remains listening; both parent and child canacceptfrom the same queue. This is the standard pre-fork server pattern — do not calllistenagain in the child.SIGPIPEis unrelated.listenitself never raisesSIGPIPE; that signal arises on writes to a closed peer afteraccept.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
socket— creates the endpointlistenwill mark as passive; always the first call in the sequencebind— assigns a local address to the socket; must run beforelistenor the call failsaccept— pulls the next pending connection off the backlog queue thatlistenestablishedsetsockopt— setSO_REUSEADDRbeforebindto avoidTIME_WAITcollisions when restarting a servershutdown— half-close an accepted connection; not used on the listening socket itself$!— holds the errno after a failedlisten; the only way to tellEADDRINUSEfromEACCESfromEOPNOTSUPP