Network info

getservbyport#

Look up a network service by its numeric port and protocol.

getservbyport consults the system services database (/etc/services on Linux, plus whatever NSS sources are configured) and returns the record for the service that listens on PORT under protocol PROTO. PORT is an integer in network byte order — the value you would pass to bind or receive from sockaddr_in, not the decimal shown in /etc/services. PROTO is a lowercase string such as "tcp" or "udp". The call wraps the C library’s getservbyport(3).

Synopsis#

getservbyport PORT, PROTO          # list context: full record
scalar getservbyport PORT, PROTO   # scalar context: service name

What you get back#

In list context, a five-element list describing the service:

my ($name, $aliases, $port, $proto) = getservbyport($port_n, "tcp");

Index

Name

Meaning

0

$name

Canonical service name, e.g. "http"

1

$aliases

Space-separated alias list, e.g. "www www-http"

2

$port

Port number in network byte order

3

$proto

Protocol name, e.g. "tcp"

If the entry does not exist the list is empty, so a list-context assignment leaves every target undef. A bare list-context call returns a single meaningless true value on miss — always assign to a list and test the first element, or call in scalar context.

In scalar context, you get the canonical service name (the same $name as above), or undef if no service is registered on that port for that protocol:

my $name = getservbyport($port_n, "tcp")
    or warn "port $port not registered for tcp";

Global state it touches#

  • $! is not reliably set on a miss — the C getservbyport(3) function has no standard errno contract for “not found”. Treat an empty list or undef return as the only trustworthy failure signal.

  • Iteration state held by the services database (shared with getservent, setservent, and endservent) is process-global and not thread-safe.

Byte-order trap#

PORT must be network byte order. The port column in /etc/services is a human decimal; the value the kernel and the C library use is the big-endian 16-bit encoding. Convert with pack / unpack or with the Socket helpers:

use Socket;

# Host decimal 80 -> network-order short:
my $port_n = pack("n", 80);            # two bytes, big-endian
my @rec    = getservbyport($port_n, "tcp");

# Or going the other way, a port extracted from sockaddr_in is
# already network order:
my ($port_n_from_peer, $iaddr) = sockaddr_in(getpeername($sock));
my $name = getservbyport($port_n_from_peer, "tcp");

Passing a host-order integer such as 80 works on little-endian hardware only by accident for low ports whose encoding happens to be non-zero in the low byte — most ports will simply miss. This is the single most common reason a getservbyport call “silently returns nothing”.

Examples#

Identify the service on port 443 over TCP:

use Socket;
my $port_n = pack("n", 443);
my ($name) = getservbyport($port_n, "tcp");
print $name, "\n";                      # https

Pair with getpeername to name an incoming connection’s port:

use Socket;
my ($peer_port_n, $peer_addr) = sockaddr_in(getpeername($client));
my $service = getservbyport($peer_port_n, "tcp") // "unknown";
print "client connected from service $service\n";

Full record dump — useful when you want the protocol or aliases:

use Socket;
my @rec = getservbyport(pack("n", 53), "udp");
if (@rec) {
    my ($name, $aliases, $port_n, $proto) = @rec;
    printf "%s (%s) on %d/%s\n",
        $name, $aliases, unpack("n", pack("n", $port_n)), $proto;
}

Scalar context, guard clause style:

my $svc = getservbyport(pack("n", $port), "tcp")
    or die "no TCP service registered on port $port";

Iterate every registered service (the underlying database is shared with getservent):

while (my ($n, $a, $p, $proto) = getservent()) {
    next unless $proto eq "tcp";
    # …do something with $n / $p…
}
endservent();

Edge cases#

  • Missing entry: empty list in list context, undef in scalar context. A bare if (getservbyport(...)) in list context is truthy even for a missing entry because of the “single meaningless true value” legacy return — always assign to a list or force scalar context.

  • Unknown protocol: an unrecognised PROTO string (e.g. "sctp" on a host whose database does not include it) is treated by the C library as no-match. The call returns empty/undef, not an error.

  • Case of PROTO: case-sensitive on most Linux libc implementations. Use lowercase "tcp" / "udp"; "TCP" will miss.

  • Host-order port: passing 80 instead of pack("n", 80) is the classic bug — see Byte-order trap above.

  • Numeric vs string PORT: Perl numifies PORT before passing to libc. A two-byte packed string works because pack with "n" produces bytes that numify deterministically on the supported platforms; if in doubt, unpack("n", $packed) first and pass the integer to keep the intent explicit.

  • Precedence with list operators: like other named unary / list operators, getservbyport binds loosely. Parenthesise when the result feeds another operator:

    getservbyport $port_n, "tcp" eq "https"     # WRONG
    (getservbyport($port_n, "tcp")) eq "https"  # correct
    
  • Threads: the underlying lookup shares state with getservent / setservent / endservent. Two threads iterating concurrently will interleave records. Use thread-local wrappers when that matters.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • getservbyname — inverse lookup, service name to port; reach for it when you know the name and want the number

  • getservent — iterate every service record; use when you need a full sweep rather than a single lookup

  • setservent — rewind the services iterator, optional STAYOPEN flag to keep the file open across fork

  • endservent — close the services database after an iteration

  • getprotobynumber — the protocol-side companion lookup; often used right after getservbyport to translate the $proto field

  • pack — build the network-order port value getservbyport expects as its first argument

  • Socket — constants and sockaddr_in helpers that produce network-order ports straight from kernel structures