Sockets

getsockname#

Return the local address of a connected or bound socket.

getsockname asks the kernel which address and port SOCKET is bound to on this end of the connection. The result is the same packed sockaddr structure the kernel hands to accept or that you would pass to bind — unpack it with the appropriate helper from Socket (for example sockaddr_in for IPv4, sockaddr_in6 for IPv6). Useful when a host has multiple interfaces and you need to know which one a client reached you on, or when you asked the kernel for an ephemeral port via bind with port 0 and now want to know the port it picked.

Synopsis#

getsockname SOCKET

What you get back#

On success, the packed sockaddr for the local end of SOCKET as a byte string whose layout matches the socket’s address family. On failure, undef with $! set (typically ENOTSOCK if SOCKET is not a socket, or EBADF if it is not an open filehandle).

The return value is opaque bytes. Do not inspect it directly — hand it to the family-appropriate unpacker:

use Socket;
my $packed = getsockname($sock) or die "getsockname: $!";
my ($port, $addr) = sockaddr_in($packed);      # IPv4

For address-family-agnostic code, call sockaddr_family on the result first and dispatch on the returned AF_* constant.

Global state it touches#

None. getsockname is a pure system-call wrapper — it does not read or write $_, $! aside, or any other interpreter global.

Examples#

Discover the ephemeral port the kernel assigned after bind(…, 0):

use Socket;
socket(my $srv, AF_INET, SOCK_STREAM, 0) or die $!;
bind($srv, sockaddr_in(0, INADDR_ANY))   or die $!;
my ($port) = sockaddr_in(getsockname($srv));
print "listening on port $port\n";

Identify which local IP a connected client reached you on, on a multi-homed host:

use Socket;
my $mysockaddr = getsockname($sock);
my ($port, $myaddr) = sockaddr_in($mysockaddr);
printf "Connect to %s [%s]\n",
    scalar gethostbyaddr($myaddr, AF_INET),
    inet_ntoa($myaddr);

IPv6 variant — unpack with sockaddr_in6:

use Socket;
my ($port, $addr) = sockaddr_in6(getsockname($sock));
printf "local: [%s]:%d\n", inet_ntop(AF_INET6, $addr), $port;

Family-agnostic dispatch when the socket could be either IPv4 or IPv6:

use Socket qw(sockaddr_family sockaddr_in sockaddr_in6
              inet_ntop AF_INET AF_INET6);
my $name = getsockname($sock) or die "getsockname: $!";
if (sockaddr_family($name) == AF_INET) {
    my ($port, $addr) = sockaddr_in($name);
    printf "%s:%d\n", inet_ntoa($addr), $port;
} else {
    my ($port, $addr) = sockaddr_in6($name);
    printf "[%s]:%d\n", inet_ntop(AF_INET6, $addr), $port;
}

Edge cases#

  • Unbound socket: A socket that has been created but never bound or connected typically returns a sockaddr with the wildcard address and port 0. It is not an error — the kernel simply reports “no local name assigned yet.”

  • Not a socket: Passing an open filehandle that is not a socket (a plain file, a pipe) returns undef with $! set to ENOTSOCK.

  • Closed filehandle: Returns undef with $! set to EBADF. Under use warnings a getsockname() on closed socket warning is emitted.

  • Unix-domain sockets: The packed form is an AF_UNIX sockaddr; unpack with unpack_sockaddr_un. The path may be shorter than what you passed to bind, and on Linux it may begin with a NUL byte for abstract-namespace sockets.

  • Wildcard address with IPv4: A socket bound to INADDR_ANY reports the wildcard address (0.0.0.0) here, not the specific interface address the peer reached. To learn the peer’s target address you must use getsockname after the kernel has routed the connection (post-accept), or consult IP_PKTINFO via getsockopt.

  • Call before bind/connect: The behaviour is platform-specific but harmless. Linux returns a zeroed sockaddr of the socket’s family; some BSDs return undef with EINVAL. Rely on it only after bind, connect, or accept have completed.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • getpeername — the mirror call: returns the remote end’s sockaddr for a connected socket

  • bind — set the local address; getsockname reads back what the kernel actually bound, including ephemeral ports chosen for you

  • accept — returns the remote sockaddr directly, so you rarely need getsockname on the accepted socket unless the listener bound to a wildcard and you want the concrete local address

  • socket — creates the socket whose local name getsockname reports

  • Socket — the module providing the unpackers (sockaddr_in, sockaddr_in6, unpack_sockaddr_un, sockaddr_family) you apply to the return value

  • getsockopt — for per-packet destination-address information (IP_PKTINFO) when a wildcard-bound socket needs to know the concrete local address of an incoming datagram