Network info

getservbyname#

Look up a network service by its textual name and protocol.

getservbyname consults the system service database (typically /etc/services, or whatever nsswitch.conf routes the services source to) and returns the entry whose name or alias matches NAME under the transport protocol named by PROTO. It is the Perl wrapper around the C library’s getservbyname(3) call, and it is how you turn "https" into 443 without hardcoding the number.

Both arguments are strings. NAME is the service name or alias ("http", "ssh", "imaps"); PROTO is the protocol name ("tcp", "udp", "sctp") — not a number, and not a SOCK_STREAM-style constant.

Synopsis#

my $port                            = getservbyname NAME, PROTO;   # scalar
my ($name, $aliases, $port, $proto) = getservbyname NAME, PROTO;   # list

What you get back#

In scalar context, the port number as a plain integer in host byte order — ready to feed to pack with "n" or to a sockaddr_in constructor. If no entry matches, the return is undef.

In list context, the four fields of the servent record:

  • $name — canonical service name (the primary name, not whichever alias you looked up by).

  • $aliases — space-separated string of alternate names.

  • $port — port number, host byte order.

  • $proto — canonical protocol name as returned by the resolver, normally equal to the PROTO you passed.

If no entry matches in list context the return is the empty list.

The port is host byte order. Network APIs expect network byte order, so pass it through pack with the "n" template — or let Socket do it via sockaddr_in.

Global state it touches#

  • Holds an open handle to the services database between calls when the database has been opened with setservent using a non-zero STAYOPEN. endservent closes it.

  • Sets $! on lookup failures that stem from a system-level error (database file missing, NSS backend unreachable). A plain “no such service” is reported by returning undef / the empty list, not by setting $!.

Examples#

Resolve a well-known service to its port:

my $port = getservbyname("https", "tcp");
print $port, "\n";                    # 443

Full record in list context:

my ($name, $aliases, $port, $proto) = getservbyname("http", "tcp");
print "$name ($aliases) -> $port/$proto\n";
                                      # www (www-http http) -> 80/tcp
                                      # (exact aliases depend on /etc/services)

Build a sockaddr_in for connect, converting the host-order port to network order with pack:

use Socket;
my $port  = getservbyname("smtp", "tcp")
    or die "smtp/tcp not in services db";
my $addr  = sockaddr_in($port, inet_aton("mail.example.com"));
socket(my $s, AF_INET, SOCK_STREAM, getprotobyname("tcp")) or die $!;
connect($s, $addr) or die "connect: $!";

Distinguish “not found” from “wrong protocol” — a service that exists under tcp but not udp returns undef when the protocol does not match:

defined(getservbyname("https", "tcp")) or die "expected 443";
defined(getservbyname("https", "udp")) or warn "no https/udp entry";

Look up by alias — aliases resolve the same as the canonical name, but the returned $name is always the canonical one:

my ($name) = getservbyname("www", "tcp");
print $name, "\n";                    # "http" on most systems

Edge cases#

  • Unknown service: returns undef in scalar context, the empty list in list context. $! is not set for a plain miss — only for underlying system errors.

  • Unknown protocol: same as an unknown service. getservbyname("ssh", "xyzzy") returns nothing; no separate error is raised.

  • Case sensitivity: service and protocol names are compared case-insensitively by the system resolver on every platform we support; "HTTPS" and "https" give the same answer.

  • Port is host byte order: passing it straight into a wire format is a bug. Use pack("n", $port) or sockaddr_in($port, $addr) — both handle the conversion.

  • NAME and PROTO are both required. There is no one-arg form; omitting PROTO is a compile-time error.

  • Precedence trap: like every named-unary-lookalike in this family, getservbyname is a list operator. Parenthesise when combining with operators:

    getservbyname "http", "tcp" == 80      # WRONG: parses as
                                           # getservbyname("http", ("tcp" == 80))
    getservbyname("http", "tcp") == 80     # right
    
  • Threads: on systems with getservbyname_r(3), Perl uses the reentrant variant transparently. On the handful of platforms that lack it, concurrent lookups from multiple threads can clobber each other’s results.

  • By-name interface: Net::servent (core) wraps this call and returns an object with named accessors, at the cost of one allocation per lookup.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • getservbyport — inverse lookup: port + protocol → service record

  • getservent — walk every entry in the services database, one record at a time

  • setservent — rewind (or persistently open) the services database before a walk

  • endservent — close the services database opened by setservent

  • getprotobyname — companion lookup for the PROTO argument when you also need its numeric protocol number

  • Socketsockaddr_in and pack_sockaddr_in consume the host-order port returned here