Функция PHP getprotobynumber(): всё, что нужно знать
Узнайте, как использовать функцию PHP getprotobynumber() для получения имени протокола по его номеру с примерами.
Сетевые протоколы передаются по сети в виде чисел, а не имён. В IP-пакете TCP — это 6, UDP — 17, ICMP — 1, и никаких человекочитаемых меток к ним не прилагается. Когда PHP-код считывает необработанный номер протокола (например, из разобранного пакета, журнала брандмауэра или вызова сети на уровне C), нередко требуется преобразовать это число обратно в понятное имя. Именно это делает функция getprotobynumber(): она находит номер протокола и возвращает его зарегистрированное имя.
В этой главе объясняется, что возвращает функция, как она читает системную базу данных протоколов, о чём следует помнить при переносимости кода и как она сочетается со своей обратной функцией getprotobyname().
Что такое функция getprotobynumber()?
getprotobynumber() — это встроенная функция PHP, которая сопоставляет числовой идентификатор протокола с его зарегистрированным именем. Она читает системную базу данных протоколов — как правило, /etc/protocols в Unix-подобных системах или %SystemRoot%\system32\drivers\etc\protocol в Windows — и возвращает соответствующее имя в виде string.
Распространённое заблуждение состоит в том, что функция возвращает array. Это не так: возвращаемое значение — обычная строка, например "tcp", или false, если протокол с таким номером не зарегистрирован в системе. Поскольку результат поиска зависит от локального файла протоколов, один и тот же номер теоретически может разрешаться по-разному в разных операционных системах, хотя широко известные номера протоколов стандартизированы IANA и одинаковы везде.
Синтаксис
getprotobynumber(int $protocol): string|falseФункция принимает один параметр:
$protocol: номер протокола для поиска (например,6для TCP).
При успешном поиске возвращает имя протокола в виде string; если номер не найден в базе данных протоколов — возвращает false.
Базовый пример
Номер протокола 6 соответствует TCP. В примере ниже выполняется поиск этого протокола, и случай неудачи обрабатывается явно с помощью строгого сравнения (===), поскольку false — единственный сигнал об ошибке:
Вывод:
Protocol number 6 is 'tcp'Используйте строгое сравнение === вместо !$protocol_name, так как корректное имя всегда является непустой строкой — но явная проверка на false делает намерение понятным и позволяет избежать граничных случаев.
Распространённые номера протоколов
Приведённые ниже широко известные номера стандартизированы IANA и присутствуют практически в каждой системе:
| Номер | Имя | Описание |
|---|---|---|
0 | ip | Internet Protocol |
1 | icmp | Internet Control Message Protocol |
2 | igmp | Internet Group Management Protocol |
6 | tcp | Transmission Control Protocol |
17 | udp | User Datagram Protocol |
41 | ipv6 | Инкапсуляция IPv6 |
47 | gre | Generic Routing Encapsulation |
58 | ipv6-icmp | ICMP для IPv6 |
Можно перебрать диапазон номеров, чтобы увидеть, какие из них распознаёт ваша система:
<?php
foreach ([1, 6, 17, 132, 9999] as $number) {
$name = getprotobynumber($number);
echo $number . ' => ' . ($name === false ? '(unknown)' : $name) . PHP_EOL;
}Номер 9999 не назначен, поэтому поиск вернёт false и выведет (unknown).
getprotobynumber() vs getprotobyname()
Эти две функции являются точными обратными функциями друг друга:
getprotobynumber(6)возвращает string"tcp".getprotobyname("tcp")возвращает целое число6.
Используйте getprotobynumber(), когда у вас есть необработанное число (из пакета, журнала или вызова сокета) и нужно получить читаемое имя. Используйте getprotobyname(), когда у вас есть имя и нужно получить число — например, чтобы передать его как аргумент $protocol при открытии необработанного сокета.
Когда это может понадобиться?
- Чтение захватов пакетов или журналов брандмауэра, в которых записывается числовое поле протокола IP-заголовка.
- Отображение понятного вывода в инструментах сетевой диагностики или мониторинга.
- Проверка того, что номер протокола известен вашей системе, прежде чем действовать на его основе.
Для работы с сетью на более высоком уровне вы чаще будете обращаться к вспомогательным функциям поиска хостов и сервисов: getservbyport() и getservbyname() сопоставляют порты с именами сервисов, а gethostbyname() разрешает имена хостов.
Заключение
getprotobynumber() преобразует числовой идентификатор протокола в его зарегистрированное имя, возвращая string (не array) или false, если номер неизвестен. Она читает локальную базу данных протоколов и является обратной функцией getprotobyname(). Ключ к правильному использованию функции — понимание того, что она возвращает обычную строку, и проверка результата на false с помощью строгого сравнения.