Sockets

accept#

Accept an incoming connection on a listening socket.

accept is the server side of the connection handshake. It waits on GENERICSOCKET — a socket that has already been created with socket, bound with bind, and placed in the listening state with listen — until a client connects, then installs a brand-new connected socket in NEWSOCKET and returns the client’s packed address. GENERICSOCKET stays in the listening state, ready for the next call. Behaviour mirrors the POSIX accept(2) system call.

Synopsis#

accept NEWSOCKET, GENERICSOCKET

What you get back#

The client’s address in the packed form used by the address family of GENERICSOCKET — the same shape you’d pass to connect or unpack with Socket::unpack_sockaddr_in for IPv4, or with Socket::unpack_sockaddr_in6 / unpack_sockaddr_un for IPv6 and Unix-domain sockets respectively. On failure returns a false value (the empty string) and sets $! to the underlying errno.

NEWSOCKET is populated as a side effect — it is a plain filehandle argument, not a return value. A bareword like CLIENT autovivifies a typeglob; a lexical filehandle like my $client is populated in place:

my $client;
accept($client, $server) or die "accept: $!";
# $client is now a readable/writable handle to the connected peer

Global state it touches#

  • $! — set on failure to the underlying errno (EINTR, EAGAIN/EWOULDBLOCK on non-blocking listeners, ECONNABORTED, EMFILE, ENFILE).

  • $^F — the system maximum file descriptor. On systems that support the close-on-exec flag, accept sets FD_CLOEXEC on the new descriptor when its number is greater than $^F (default 2, covering the standard streams). Raise $^F before accept if you want the accepted socket to survive exec.

Examples#

Minimal TCP echo-style accept loop:

use Socket;

socket(my $server, PF_INET, SOCK_STREAM, getprotobyname("tcp"))
    or die "socket: $!";
bind($server, sockaddr_in(8080, INADDR_ANY)) or die "bind: $!";
listen($server, SOMAXCONN)                   or die "listen: $!";

while (my $peer = accept(my $client, $server)) {
    my ($port, $iaddr) = sockaddr_in($peer);
    print $client "hello ", inet_ntoa($iaddr), ":$port\n";
    close $client;
}
die "accept: $!";   # loop exits only on error

Unpack the returned address for logging:

use Socket;

my $peer = accept(my $client, $server)
    or die "accept: $!";
my ($port, $iaddr) = sockaddr_in($peer);
printf "connection from %s port %d\n", inet_ntoa($iaddr), $port;

Non-blocking accept. Put $server in non-blocking mode first; a pending-connection-less call then returns false with $! set to EAGAIN or EWOULDBLOCK:

use Errno qw(EAGAIN EWOULDBLOCK);
use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);

my $flags = fcntl($server, F_GETFL, 0);
fcntl($server, F_SETFL, $flags | O_NONBLOCK);

my $peer = accept(my $client, $server);
if (!$peer) {
    if ($! == EAGAIN || $! == EWOULDBLOCK) {
        # no pending connection — try again later
    } else {
        die "accept: $!";
    }
}

Preserve the accepted socket across exec by raising $^F so the runtime does not set FD_CLOEXEC:

local $^F = 10_000;
accept(my $client, $server) or die "accept: $!";
exec "/usr/libexec/handler", fileno($client);

Edge cases#

  • GENERICSOCKET not listeningaccept fails with $! set to EINVAL. Call listen on the server socket first.

  • NEWSOCKET already open — the existing handle is silently closed before the new descriptor is installed, exactly as for open and socket. If the old handle was the only reference to a buffered stream, any unflushed data is lost. Close explicitly beforehand when that matters.

  • Signal during the call — a signal delivered while accept is blocked makes the underlying syscall return EINTR. pperl does not auto-restart: accept returns false and leaves $! set to EINTR. Wrap in a retry loop if your signal handlers do not terminate the process.

  • Descriptor exhaustionEMFILE (process limit) or ENFILE (system limit) on a busy server is the common reason accept starts failing under load. Treat them as transient; close idle clients and retry.

  • Address-family mismatch of the packed return value — the packed buffer follows the family of GENERICSOCKET. Unpacking a Unix-domain address with Socket::unpack_sockaddr_in produces garbage. Track the family yourself or use Socket::sockaddr_family to dispatch.

  • Parentheses are optional, commas are notaccept $c, $s and accept($c, $s) both work; accept $c $s is a syntax error.

  • List vs scalar context — the packed-address return is a byte string; list context does not expand it into (port, addr). Call sockaddr_in / equivalent to unpack.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • socket — create the server socket that accept waits on

  • bind — attach the server socket to a local address before listen and accept

  • listen — mandatory step between bind and accept; sets the backlog depth

  • connect — the client-side counterpart; accept returns the address a connect call supplied

  • getpeername — recover the same packed address later from NEWSOCKET itself

  • Socket — the constants (PF_INET, SOCK_STREAM, INADDR_ANY) and packers (sockaddr_in, unpack_sockaddr_in) that turn the packed return value into something usable

  • $^F — threshold that controls whether accept sets FD_CLOEXEC on the new descriptor