--- name: getservbyport signature: 'getservbyport PORT, PROTO' since: 5.0 status: documented categories: ["Network info"] --- ```{index} single: getservbyport; Perl built-in ``` *[Network info](../perlfunc-by-category)* # 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`](bind) or receive from [`sockaddr_in`](../../Socket), 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 ```perl 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: ```perl 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`](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`](undef) if no service is registered on that port for that protocol: ```perl my $name = getservbyport($port_n, "tcp") or warn "port $port not registered for tcp"; ``` ## Global state it touches - [`$!`](../perlvar) 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`](undef) return as the only trustworthy failure signal. - Iteration state held by the services database (shared with [`getservent`](getservent), [`setservent`](setservent), and [`endservent`](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`](pack) / [`unpack`](unpack) or with the `Socket` helpers: ```perl 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: ```perl use Socket; my $port_n = pack("n", 443); my ($name) = getservbyport($port_n, "tcp"); print $name, "\n"; # https ``` Pair with [`getpeername`](getpeername) to name an incoming connection's port: ```perl 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: ```perl 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: ```perl 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`](getservent)): ```perl 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`](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`](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: ```perl getservbyport $port_n, "tcp" eq "https" # WRONG (getservbyport($port_n, "tcp")) eq "https" # correct ``` - **Threads**: the underlying lookup shares state with [`getservent`](getservent) / [`setservent`](setservent) / [`endservent`](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`](getservbyname) — inverse lookup, service name to port; reach for it when you know the name and want the number - [`getservent`](getservent) — iterate every service record; use when you need a full sweep rather than a single lookup - [`setservent`](setservent) — rewind the services iterator, optional `STAYOPEN` flag to keep the file open across `fork` - [`endservent`](endservent) — close the services database after an iteration - [`getprotobynumber`](getprotobynumber) — the protocol-side companion lookup; often used right after `getservbyport` to translate the `$proto` field - [`pack`](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