Sockets

socketpair#

Create an unnamed, connected pair of sockets that talk to each other.

socketpair opens two fresh filehandles in SOCKET1 and SOCKET2 already wired together, so anything written to one comes out of the other. No addresses, no bind, no listen, no accept. The commonest use is talking to a child process created by fork — each side keeps one handle and closes the other.

Synopsis#

use Socket;
socketpair(SOCKET1, SOCKET2, DOMAIN, TYPE, PROTOCOL) or die $!;
socketpair(my $s1, my $s2, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die $!;

What you get back#

True on success, false on failure (with $! set). On success both filehandle arguments are populated with fresh handles; on failure they are left untouched. Always check the return value — every domain/type/protocol combination is platform-dependent.

socketpair(my $a, my $b, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
    or die "socketpair: $!";

The DOMAIN, TYPE, and PROTOCOL constants come from the Socket module. AF_UNIX with SOCK_STREAM and PF_UNSPEC is the portable default.

Global state it touches#

  • $! is set on failure to the system errno.

  • $^F — the maximum system file descriptor below which close-on-exec is not set. On systems with FD_CLOEXEC, descriptors above $^F get close-on-exec automatically; below it, they survive exec. Default is 2 (stdin/stdout/stderr). Raise it before socketpair if you want the new handles to be inherited across exec.

Examples#

Plain parent/child pipe using a stream socketpair. Each side closes the end it does not need, so EOF propagates correctly:

use Socket;

socketpair(my $child, my $parent, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
    or die "socketpair: $!";

my $pid = fork // die "fork: $!";
if ($pid == 0) {
    close $child;
    print $parent "hello from child\n";
    close $parent;
    exit;
}
close $parent;
chomp(my $msg = <$child>);          # "hello from child"
waitpid $pid, 0;

Bidirectional stream: both processes read and write on the same handle. No shutdown is needed because neither side is closing a direction early:

use Socket;

socketpair(my $a, my $b, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die $!;
my $pid = fork // die $!;
if ($pid == 0) {
    close $a;
    while (my $line = <$b>) {
        chomp $line;
        print $b "echo: $line\n";
    }
    exit;
}
close $b;
print $a "ping\n";
chomp(my $reply = <$a>);            # "echo: ping"
close $a;
waitpid $pid, 0;

Emulating pipe with socketpair. shutdown turns a bidirectional socket into a one-way channel:

use Socket;
socketpair(my $rdr, my $wtr, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die $!;
shutdown($rdr, 1);                  # reader cannot write
shutdown($wtr, 0);                  # writer cannot read

Datagram pair — messages preserve boundaries, so a single recv returns exactly one send:

use Socket;
socketpair(my $a, my $b, AF_UNIX, SOCK_DGRAM, PF_UNSPEC) or die $!;
send($a, "one", 0)   or die $!;
send($a, "two", 0)   or die $!;
recv($b, my $m1, 64, 0);            # "one"
recv($b, my $m2, 64, 0);            # "two"

Edge cases#

  • AF_UNIX is the only portable domain. On most systems socketpair only works with AF_UNIX; other families return EAFNOSUPPORT. Use the constant, not a hard-coded 1.

  • Unbuffered output. Stream socketpair handles buffer like any other filehandle. Set $| on the writer (after selecting it) or the reader will block waiting for output that is still in the parent’s buffer. autoflush from IO::Handle is the usual form:

    $parent->autoflush(1);
    
  • Close both ends or EOF never arrives. A stream socketpair delivers EOF on a reader only after every writable copy of the peer handle is closed. A child that forgets to close the parent’s end will hang the parent on <$handle> forever.

  • Close-on-exec via $^F. Filehandles whose numeric descriptor is greater than $^F get FD_CLOEXEC on platforms that support it, so they vanish across exec. Raise $^F before the call if the handle must survive an exec.

  • Unimplemented on the platform. If the underlying socketpair(2) syscall does not exist, perl raises an exception rather than returning false. Trap with eval if you need to fall back.

  • Datagram vs stream. SOCK_STREAM is byte-oriented (no message boundaries, use newline framing or length prefixes). SOCK_DGRAM preserves message boundaries but loses them silently if the receive buffer is smaller than the message.

  • PROTOCOL. For AF_UNIX the protocol is ignored; PF_UNSPEC (or 0) is conventional. Specifying a protocol that does not match the domain/type combination returns EPROTONOSUPPORT.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • socket — create a single socket when only one end is yours (the other comes from the network via accept or connect)

  • pipe — unidirectional byte channel; lighter weight than socketpair but cannot do bidirectional traffic on one call

  • send / recv — message-oriented I/O, required for SOCK_DGRAM socketpairs

  • fork — the typical partner: one socketpair before the fork gives parent and child a ready-made conduit

  • Socket — source of AF_UNIX, SOCK_STREAM, SOCK_DGRAM, PF_UNSPEC and the other constants socketpair expects

  • $^F — threshold above which new descriptors get close-on-exec; matters when the handles must survive exec