Функция PHP getprotobyname(): всё, что нужно знать
Узнайте, как PHP-функция getprotobyname() возвращает номер протокола по его имени, с примерами и советами по обработке ошибок.
При работе с низкоуровневыми сетевыми возможностями в PHP иногда известно имя протокола, например tcp или udp, а нужен его числовой номер — значение, присвоенное этому протоколу организацией IANA и используемое в заголовках IP-пакетов. Функция getprotobyname() выполняет именно такой поиск. На этой странице рассматриваются её синтаксис, возвращаемое значение, распространённые номера протоколов, обработка ошибок и связь с другими функциями поиска протоколов и служб в PHP.
Что такое функция getprotobyname()?
getprotobyname() — это встроенная функция PHP, которая преобразует имя протокола в соответствующий номер. Она читает системную базу данных протоколов — как правило, /etc/protocols в Unix-подобных системах и %SystemRoot%\System32\drivers\etc\protocol в Windows, — поэтому понимает имена, перечисленные там (например, ip, icmp, tcp, udp, ipv6).
Это обратная функция для getprotobynumber(), которая преобразует номер обратно в имя. Числовой номер протокола обычно нужен при открытии сырого сокета с помощью socket_create() и аналогичных низкоуровневых API, где протокол должен быть указан численно.
Синтаксис
getprotobyname(string $protocol): int|falseФункция принимает один параметр:
$protocol— имя протокола для поиска. Поиск нечувствителен к регистру, поэтому"TCP"и"tcp"дают одинаковый результат.
Функция возвращает целое число, представляющее номер протокола, или false, если имя протокола не найдено в системной базе данных.
Базовый пример
Вот как получить номер протокола tcp и обработать случай, когда поиск не дал результата:
Для "tcp" выводится:
The protocol number for protocol name tcp is 6Обратите внимание на строгое сравнение === false. Поскольку наименьший допустимый номер протокола равен 0 (протокол ip), нестрогая проверка вида if (!$protocol_number) ошибочно расценит успешный поиск ip как неудачу. Всегда сравнивайте с false с помощью ===.
Распространённые номера протоколов
Это значения, с которыми вы будете сталкиваться чаще всего. Они берутся напрямую из системной базы данных протоколов, поэтому стабильны на всех платформах:
| Имя протокола | Номер | Значение |
|---|---|---|
ip | 0 | Internet Protocol |
icmp | 1 | Internet Control Message Protocol |
tcp | 6 | Transmission Control Protocol |
udp | 17 | User Datagram Protocol |
ipv6 | 41 | Internet Protocol v6 |
Поиск нескольких протоколов
Можно перебрать список имён и вывести каждый результат, корректно обрабатывая неизвестные имена:
<?php
$protocols = ["tcp", "udp", "icmp", "bogus"];
foreach ($protocols as $name) {
$number = getprotobyname($name);
if ($number === false) {
echo "$name: not found\n";
} else {
echo "$name => $number\n";
}
}Вывод:
tcp => 6
udp => 17
icmp => 1
bogus: not foundКогда это используется?
В повседневной веб-разработке номера протоколов редко нужны — fopen(), cURL и потоковые обёртки принимают URL, а не числа. К getprotobyname() обращаются, когда требуется опуститься на уровень ниже:
- Создание сырых сокетов.
socket_create(AF_INET, SOCK_RAW, getprotobyname("icmp"))передаёт номер протокола в сокет. Жёстко заданное1работает, ноgetprotobyname("icmp")выражает намерение явно и остаётся корректным, если база данных отличается. - Формирование или разбор IP-пакетов, где поле протокола является числовым.
- Сетевые утилиты и диагностика, которые выводят и имя, и номер протокола.
Связанные функции
getprotobynumber()— обратный поиск: по номеру возвращает имя.getservbyname()— преобразует имя службы (например,http) и протокол в номер порта.getservbyport()— обратная функция: по номеру порта возвращает имя службы.fsockopen()— открывает сетевое соединение по хосту и порту.
Заключение
getprotobyname() преобразует имя протокола в числовой номер, определённый в системной базе данных, и возвращает false, если имя не найдено. Не забывайте проверять результат строгим сравнением === false, чтобы допустимое значение 0 для протокола ip не было ошибочно принято за сбой; используйте эту функцию всякий раз, когда низкоуровневый сетевой API ожидает числовой номер протокола, а не его имя.