Сетевые функции PHP
Обзор встроенных сетевых функций PHP: разрешение имён, сокеты, потоки и работа с IP-адресами без сторонних библиотек.
Сетевое взаимодействие лежит в основе большинства веб-приложений: разрешение имён хостов, открытие сокетов, обращение к другим серверам и проверка IP-адресов. PHP поставляется со встроенным набором сетевых функций, которые позволяют выполнять всё это без сторонних библиотек. В этой главе рассказывается, что это за функции, когда применять каждую из групп и как правильно их использовать — с готовыми примерами кода.
Что такое сетевые функции PHP?
Сетевые функции PHP — это встроенные функции, позволяющие скрипту взаимодействовать по сети. С их помощью можно:
- Разрешать имена — преобразовывать имя хоста, например
www.example.com, в IP-адрес (и обратно). - Открывать соединения — создавать TCP/UDP-сокет к другому серверу и обмениваться «сырыми» байтами.
- Читать и записывать потоки — отправлять запросы и получать ответы.
- Работать с IP-адресами — конвертировать между удобочитаемой строкой и упакованным двоичным представлением для IPv4 и IPv6.
Поскольку эти функции входят в ядро PHP, устанавливать pecl install или Composer-пакет не нужно — они всегда доступны.
Функции DNS и поиска хостов
Прежде чем подключиться к серверу, как правило, нужно узнать его IP-адрес. Следующие функции отвечают за разрешение имён.
| Функция | Что делает |
|---|---|
gethostbyname() | Возвращает IPv4-адрес для имени хоста. |
gethostbyaddr() | Возвращает имя хоста для IP-адреса (обратный поиск). |
gethostbynamel() | Возвращает список всех IPv4-адресов для имени хоста. |
checkdnsrr() | Проверяет наличие DNS-записей (A, MX и др.) для хоста. |
dns_get_record() | Получает полные DNS-записи для хоста. |
Типичная комбинация — gethostbyname() для получения IP и checkdnsrr() для проверки того, что хост действительно имеет DNS-записи. Именно об этом спрашивается в практическом задании ниже.
<?php
$host = "localhost";
// Resolve a hostname to its IPv4 address.
$ip = gethostbyname($host);
echo "IP for {$host}: {$ip}\n";
// Reverse lookup: IP back to a hostname.
echo "Host for {$ip}: " . gethostbyaddr($ip) . "\n";Если имя не удаётся разрешить,
gethostbyname()возвращает исходную строку без изменений, а не бросает ошибку — всегда сравнивайте результат с оригиналом, прежде чем доверять ему.
Функции для работы с сокетами
Когда нужно «сырое» соединение с другим сервером, используйте потоковый сокет. Современная и рекомендуемая функция — stream_socket_client(); старая fsockopen() тоже работает, но API потоков более гибкий.
| Функция | Применение |
|---|---|
stream_socket_client() | Открыть клиентское соединение (рекомендуется). |
stream_socket_server() | Принимать входящие соединения (создание сервера). |
pfsockopen() | Открыть постоянный сокет, переживающий несколько запросов. |
fsockopen() | Устаревший способ открыть сокет; предпочтительнее потоковая версия. |
Ниже — минимальный HTTP-запрос, выполненный вручную через сокет:
<?php
$fp = stream_socket_client("tcp://www.example.com:80", $errno, $errstr, 30);
if (!$fp) {
echo "Connection failed: {$errstr} ({$errno})\n";
} else {
$request = "GET / HTTP/1.1\r\n";
$request .= "Host: www.example.com\r\n";
$request .= "Connection: Close\r\n\r\n";
fwrite($fp, $request);
while (!feof($fp)) {
echo fgets($fp, 128); // read the response line by line
}
fclose($fp);
}Этот код открывает TCP-соединение на порт 80, отправляет «сырой» GET-запрос и выводит ответ сервера. В реальных проектах запросы редко пишут вручную — смотрите file_get_contents() для простых запросов или используйте cURL / Guzzle для работы с заголовками, редиректами и HTTPS.
Функции потокового ввода-вывода
После открытия сокета (или любого потока) для чтения и записи байтов используются следующие функции. Они те же, что применяются для работы с файлами, поскольку PHP трактует сокеты и файлы как потоки.
fgets()— читать одну строку.fgetc()— читать один символ.fread()— читать фиксированное количество байтов.fwrite()— записывать данные в поток.feof()— проверять, достигнут ли конец потока.
Функции преобразования IP-адресов
Эти функции конвертируют IP-адрес между строковым представлением (с точками или двоеточиями) и упакованным двоичным форматом. Они необходимы при компактном хранении адресов или их сравнении.
| Функция | Направление | Семейство |
|---|---|---|
inet_pton() | строка → упакованный двоичный | IPv4 и IPv6 |
inet_ntop() | упакованный двоичный → строка | IPv4 и IPv6 |
ip2long() | строка IPv4 → целое число | только IPv4 |
long2ip() | целое число → строка IPv4 | только IPv4 |
<?php
$ip = "192.168.1.1";
// Pack the IPv4 string into binary, then expand it back.
$packed = inet_pton($ip);
echo "Round-trip: " . inet_ntop($packed) . "\n";
// ip2long stores an IPv4 address as a single integer (handy for databases).
$long = ip2long($ip);
echo "As integer: {$long}\n";
echo "Back to string: " . long2ip($long) . "\n";
inet_pton()/inet_ntop()работают с IPv4 и IPv6, тогда какip2long()/long2ip()— только с IPv4. Используйте паруinet_*, если код должен поддерживать IPv6.
Проверка IP-адресов
Чтобы убедиться, что строка является допустимым IP-адресом (например, из пользовательского ввода), используйте filter_var() вместо самостоятельно написанного регулярного выражения:
<?php
$candidates = ["192.168.0.1", "999.1.1.1", "::1"];
foreach ($candidates as $value) {
$valid = filter_var($value, FILTER_VALIDATE_IP) !== false;
echo $value . " => " . ($valid ? "valid" : "invalid") . "\n";
}Этот код проверяет IPv4 и IPv6 за один вызов; добавьте флаг FILTER_FLAG_IPV4 или FILTER_FLAG_IPV6, чтобы ограничить проверку конкретным семейством.
Когда использовать эти функции?
- Низкоуровневые протоколы — построение SMTP, FTP или собственного TCP-клиента, где вы управляете байтами в канале.
- Проверка доступности сервиса — убедиться, что хост разрешается (
checkdnsrr()), или что порт доступен (stream_socket_client()с коротким тайм-аутом). - Хранение IP-данных — упаковка адресов с помощью
inet_pton()илиip2long()для экономии места и выполнения запросов по диапазону. - Для обычных HTTP-вызовов API предпочтительнее cURL или клиентская библиотека; сокетные функции нужны, когда требуется более тонкий контроль, чем они предоставляют.
Заключение
Сетевые функции PHP охватывают всё — от DNS-запросов до «сырых» сокетов и конвертации IP-адресов — без каких-либо внешних зависимостей. Запомните три группы: разрешить хост (gethostbyname(), checkdnsrr()), подключиться к нему (stream_socket_client()) и читать/записывать поток (fgets(), fwrite()). Для более высокоуровневых задач используйте cURL и Guzzle, а к этим функциям обращайтесь только тогда, когда нужен более низкий уровень управления.