getpeername#
Return the address of the remote end of a connected socket.
getpeername asks the kernel who is on the other side of SOCKET and
returns the answer as a packed sockaddr byte string — the same shape
connect took and the same shape accept
returned. You then hand that byte string to an unpacker from
Socket (or Socket::unpack_sockaddr_in,
Socket::unpack_sockaddr_in6,
Socket::unpack_sockaddr_un) to pull out the
port, address, or path.
This is the companion to getsockname, which returns
the local end of the same socket.
Synopsis#
use Socket;
my $peer = getpeername SOCKET;
my ($port, $iaddr) = unpack_sockaddr_in($peer);
What you get back#
A packed sockaddr byte string on success, undef on failure
(with $! set — typically ENOTCONN when the socket has no
peer, or EBADF when SOCKET is not an open file descriptor).
The byte string is opaque. Its layout depends on the socket’s address family; always decode it with an unpacker that matches the family you expect:
AF_INET→Socket::unpack_sockaddr_inreturns($port, $iaddr)where$iaddris the 4-byte packed IPv4 address.AF_INET6→Socket::unpack_sockaddr_in6returns($port, $iaddr, $scope_id, $flowinfo).AF_UNIX→Socket::unpack_sockaddr_unreturns the peer’s filesystem path.
If you do not know the family at the call site, ask
Socket::sockaddr_family first:
my $peer = getpeername $sock;
my $family = sockaddr_family($peer);
Global state it touches#
getpeername reads the file-descriptor state of SOCKET. It sets
$! on failure and does not otherwise touch interpreter
globals. It does not interact with $_, the selected
filehandle, or output separators.
Examples#
Look up the remote IPv4 peer of a client-side TCP socket and render it in dotted-quad form:
use Socket;
my $peer = getpeername($sock)
or die "getpeername: $!";
my ($port, $iaddr) = unpack_sockaddr_in($peer);
printf "peer is %s:%d\n", inet_ntoa($iaddr), $port;
Server side: every socket returned by accept is already
connected, and accept itself hands back the peer address.
getpeername is useful later, when that packed address has not been
kept around:
while (my $client = accept(my $conn, $listen)) {
handle($conn);
}
sub handle {
my ($conn) = @_;
my $peer = getpeername($conn) or return;
my ($port, $iaddr) = unpack_sockaddr_in($peer);
warn "request from ", inet_ntoa($iaddr), ":$port\n";
# ...
}
Resolve the peer back to a hostname — note that this issues a blocking DNS lookup:
use Socket;
my $peer = getpeername($sock);
my ($port, $iaddr) = unpack_sockaddr_in($peer);
my $name = gethostbyaddr($iaddr, AF_INET);
print "connected to ", $name // inet_ntoa($iaddr), "\n";
Mixed IPv4 / IPv6 code — decode generically via the address family:
use Socket qw(sockaddr_family unpack_sockaddr_in unpack_sockaddr_in6
AF_INET AF_INET6 inet_ntop);
my $peer = getpeername($sock) or die "getpeername: $!";
my $fam = sockaddr_family($peer);
if ($fam == AF_INET) {
my ($port, $iaddr) = unpack_sockaddr_in($peer);
printf "v4 %s:%d\n", inet_ntop(AF_INET, $iaddr), $port;
}
elsif ($fam == AF_INET6) {
my ($port, $iaddr) = unpack_sockaddr_in6($peer);
printf "v6 [%s]:%d\n", inet_ntop(AF_INET6, $iaddr), $port;
}
Probing whether a socket is connected at all — the ENOTCONN path is
the well-defined way to ask:
if (defined getpeername($sock)) {
# connected
} else {
# $! == ENOTCONN for an unconnected socket
}
Edge cases#
Unconnected socket: a socket that has been
socket’d but not yetconnect’d oraccept’d has no peer.getpeernamereturnsundefand sets$!toENOTCONN.Non-socket filehandle: passing a plain file or pipe yields
undefwith$!set toENOTSOCK.Closed or invalid filehandle: returns
undefwith$!set toEBADF. Underuse warningsagetpeername() on closed socketwarning is emitted.Datagram sockets:
getpeernameonly returns an address when theSOCK_DGRAMsocket has beenconnect’d to a default peer; otherwise it fails withENOTCONNeven though the socket is usable viarecv/send.AF_UNIXwith an unbound peer: a Unix-domain socket whose peer never calledbindreturns a packedsockaddr_unwith an empty path.Socket::unpack_sockaddr_ungives back the empty string.After
shutdown:getpeernamestill succeeds as long as the descriptor is open; shutdown tears down data flow, not the kernel’s record of the peer.SOCKET is a parsed filehandle token: like other socket built-ins, the argument is parsed as a filehandle, not evaluated as a general expression.
getpeername $handles[0]is a syntax error; use a scalar holding the handle, or*{...}dereferencing.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
getsockname— mirror call that returns the local end of the same socket; pairs withgetpeernamewhen logging both ends of a connectionaccept— already hands you the peer address for a freshly accepted server-side socket; usegetpeernamelater when that address was not retainedconnect— the call that establishes the peer in the first place; the address you pass toconnectis whatgetpeernamewill hand back afterwardsSocket— provides the unpackers (unpack_sockaddr_in,unpack_sockaddr_in6,unpack_sockaddr_un) andsockaddr_familyneeded to interpret the returned byte stringgethostbyaddr— turns the packed IPv4 address from the unpacker into a hostname$!— carries the reason on failure (ENOTCONN,ENOTSOCK,EBADF)