Функция PHP getservbyname(): всё, что нужно знать
Функция PHP getservbyname() позволяет получить номер порта по имени службы. Узнайте синтаксис, примеры использования и типичные ошибки.
Сетевые службы идентифицируются общеизвестными именами, такими как http, ftp или smtp, однако операционная система маршрутизирует трафик по номеру порта (80, 21, 25 и т. д.). Функция PHP getservbyname() выполняет поиск этого номера порта, обращаясь к той же базе данных служб, которую использует остальная часть системы. На этой странице описаны синтаксис, принцип работы базы данных, типичные сценарии использования и возможные проблемы.
Синтаксис
getservbyname(string $service, string $protocol): int|falseФункция принимает два обязательных параметра:
$service— имя интернет-службы, например"http","ssh"или"smtp".$protocol— транспортный протокол:"tcp"или"udp". Вопреки утверждениям многих устаревших документаций, этот аргумент не является необязательным — его необходимо передавать явно.
В случае успеха функция возвращает номер порта как целое число (integer), а если пара служба/протокол не найдена — false. Поскольку false и допустимый номер порта могут вести себя схожим образом в контексте «ложных» значений, при проверке на ошибку всегда используйте строгий оператор ===.
Откуда берутся данные
getservbyname() не устанавливает никаких соединений и не делает предположений. Функция читает локальную таблицу поиска:
- На Linux и macOS это файл
/etc/services. - На Windows —
%SystemRoot%\system32\drivers\etc\services.
Если службы нет в этом файле, поиск завершится неудачей, даже если служба «очевидно» существует. Результат, таким образом, зависит от конкретной машины, на которой выполняется скрипт, а не является универсальной константой.
Базовый пример
Проверка === false важна: она чётко отделяет реальный сбой от допустимого результата, например порта 0 (который был бы «ложным» при нестрогом сравнении ==).
Поиск нескольких служб
На практике часто требуется разрешить сразу целый набор имён — например, для формирования отчёта о брандмауэре или проверки конфигурации:
<?php
$services = ["http", "https", "ftp", "smtp", "ssh"];
foreach ($services as $name) {
$port = getservbyname($name, "tcp");
echo $port === false
? "{$name}: not found\n"
: "{$name}: {$port}\n";
}
/*
Output:
http: 80
https: 443
ftp: 21
smtp: 25
ssh: 22
*/TCP против UDP
Одно и то же имя службы может разрешаться в разные записи в зависимости от протокола, а некоторые службы существуют только для одного из них. Всегда передавайте тот протокол, который вам действительно нужен:
<?php
var_dump(getservbyname("domain", "tcp")); // int(53) — DNS over TCP
var_dump(getservbyname("domain", "udp")); // int(53) — DNS over UDP
var_dump(getservbyname("ntp", "udp")); // int(123)
var_dump(getservbyname("madeup", "tcp")); // bool(false) — unknown serviceКогда это использовать?
- Динамическое построение сетевых клиентов. Разрешите имя службы в номер порта перед открытием сокета с помощью
fsockopen()илиpfsockopen(), чтобы в коде было читаемое"smtp"вместо магического числа25. - Проверка конфигурации. Убедитесь, что имя службы из файла конфигурации действительно известно хосту, прежде чем использовать его.
- Отчёты и инструментарий. Преобразуйте понятные человеку имена служб в номера портов для журналов, панелей мониторинга или правил брандмауэра.
Связанные функции
getservbyport()— обратная операция: по номеру порта и протоколу возвращает имя службы.getprotobyname()— поиск номера протокола (например,tcp→6) по его имени.
Типичные ошибки
- Оба аргумента обязательны. Пропуск
$protocolвызовет ошибку; неявного значения по умолчанию нет. - Только строгое сравнение. Используйте
=== falseдля обнаружения ошибки, чтобы не спутать её с портом0или граничными случаями числовых строк. - Результат зависит от хоста. Ответ берётся из локальной базы данных служб; имя, неизвестное одной машине, может успешно разрешиться на другой.
- Функция работает офлайн. Никакого DNS, никакой сети — только локальный поиск по таблице. Это быстро и безопасно вызывать часто.
Резюме
getservbyname() отображает имя службы и протокол на номер порта, используя базу данных служб операционной системы, и возвращает целое число — номер порта, или false, если пара не найдена. Используйте её в паре с getservbyport() для обратного поиска и с fsockopen(), когда нужно превратить этот порт в реальное соединение.