Учебник РНР (перевод Alexandr Pyramidin) Размещено на PHPClub.Net
Назад Вперёд

XCVI. Функции сокетов

Предупреждение!

Это расширение является ЭКСПЕРИМЕНТАЛЬНЫМ. Поведение этого расширения, имена его функций и всё, что задокументировано, может измениться в последующих релизах РНР без предупреждения. Вы предупреждены и можете использовать это расширение только под вашу ответственность.

Расширение сокетов реализует низкоуровневый интерфейс функций сообщений через сокеты на основе популярных BSD-сокетов, давая возможность работать и как серверу сокетов, и как клиенту.

Функции сокетов, описанные здесь, являются частью расширения PHP, которое обязано быть подключено на этапе компиляции с помощью опции --enable-sockets option в configure.

О более общем клиентском интерфейсе сокетов см. fsockopen() и pfsockopen().

При использовании этих функций важно помнить, что, хотя многие из них имеют имена, аналогичные их двойникам языка C, они часто имеют разные объявления. Обязательно прочтите описания, чтобы исключить конфликты.

Расширение сокетов было написано с целью предоставить интерфейс для мощных BSD-сокетов. Особое внимание было обращено на то, чтобы эти функции хорошо работали в реализациях как для Win32, так и Unix. Почти все функции сокетов могут потерпеть неудачу при определённых условиях и, следовательно, выдать сообщение E_WARNING с описанием ошибки. Иногда это не происходит по желанию разработчика. Например, функция socket_read() может выдать сообщение E_WARNING, если соединение было внезапно разорвано. Обычно предупреждения подавляются операцией @, а код ошибки отлавливается в приложении функцией socket_last_error(). Вы можете вызвать функцию socket_strerror() с кодом ошибки, чтобы получить строку с описанием этой ошибки. См. дополнительно описания функций.

Примечание: Сообщения E_WARNING, сгенерированные расширением сокетов, выводятся на английском, а получаемое сообщение об ошибке будет зависеть от текущих локальных установок (LC_MESSAGES):

Warning! - socket_bind() unable to bind address [98]: Die Adresse wird bereits verwendet

Те, кто мало знаком с программированием сокетов, могут найти соответствующий материал на Unix man-страницах; в web также имеется большое количество учебной информации о программировании сокетов на C, большая часть которой может быть применена, с некоторыми изменениями, для программирования сокетов в PHP. UNIX Socket FAQ может стать хорошим началом.

Пример 1. Сокет: Простой TCP/IP-сервер

Это пример простого talkback-сервера. Измените переменные address и port для ваших установок и запустите. Вы можете затем соединиться с сервером командой вроде этой: telnet 192.168.1.53 10000 (где address и port соответствуют вашим установкам). Всё, что вы напечатаете, будет затем выведено на стороне сервера и возвращено вам обратно. Для отсоединения введите 'quit'.

#!/usr/local/bin/php -q
<?php
error_reporting (E_ALL);

/* Разрешить скрипту зависнуть в ожидании соединений. */
set_time_limit (0);

/* Включить неявную очистку вывода, и мы увидим всё получаемое
 * по мере поступления. */
ob_implicit_flush ();

$address = '192.168.1.53';
$port = 10000;

if (($sock = socket_create (AF_INET, SOCK_STREAM, 0)) < 0) {
    echo "socket_create() failed: reason: " . socket_strerror ($sock) . "\n";
}

if (($ret = socket_bind ($sock, $address, $port)) < 0) {
    echo "socket_bind() failed: reason: " . socket_strerror ($ret) . "\n";
}

if (($ret = socket_listen ($sock, 5)) < 0) {
    echo "socket_listen() failed: reason: " . socket_strerror ($ret) . "\n";
}

do {
    if (($msgsock = socket_accept($sock)) < 0) {
        echo "socket_accept() failed: reason: " . socket_strerror ($msgsock) . "\n";
        break;
    }
    /* Отправить инструкции. */
    $msg = "\nWelcome to the PHP Test Server. \n" .
        "To quit, type 'quit'. To shut down the server type 'shutdown'.\n";
    socket_write($msgsock, $msg, strlen($msg));

    do {
        if (FALSE === ($buf = socket_read ($msgsock, 2048))) {
            echo "socket_read() failed: reason: " . socket_strerror ($ret) . "\n";
            break 2;
        }
        if (!$buf = trim ($buf)) {
            continue;
        }
        if ($buf == 'quit') {
            break;
        }
        if ($buf == 'shutdown') {
            socket_close ($msgsock);
            break 2;
        }
        $talkback = "PHP: You said '$buf'.\n";
        socket_write ($msgsock, $talkback, strlen ($talkback));
        echo "$buf\n";
    } while (true);
    socket_close ($msgsock);
} while (true);

socket_close ($sock);
?>

Пример 2. Сокет: простой TCP/IP-клиент

Это простой HTTP-клент. Он соединяет со страницей, отправляет HEAD-запрос, возвращает ответ и выходит.

<?php
error_reporting (E_ALL);

echo "<h2>TCP/IP Connection</h2>\n";

/* Получить порт для WWW-сервиса. */
$service_port = getservbyname ('www', 'tcp');

/* Получить IP-адрес для целевого хоста. */
$address = gethostbyname ('www.example.com');

/* Создать TCP/IP-сокет. */
$socket = socket_create (AF_INET, SOCK_STREAM, 0);
if ($socket < 0) {
    echo "socket_create() failed: reason: " . socket_strerror ($socket) . "\n";
} else {
    echo "OK.\n";
}

echo "Attempting to connect to '$address' on port '$service_port'...";
$result = socket_connect ($socket, $address, $service_port);
if ($result < 0) {
 echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n";
} else {
    echo "OK.\n";
}

$in = "HEAD / HTTP/1.0\r\n\r\n";
$out = '';

echo "Sending HTTP HEAD request...";
socket_write ($socket, $in, strlen ($in));
echo "OK.\n";

echo "Reading response:\n\n";
while ($out = socket_read ($socket, 2048)) {
    echo $out;
}

echo "Closing socket...";
socket_close ($socket);
echo "OK.\n\n";
?>
Содержание
socket_accept - принимает соединение на сокете
socket_bind - связывает имя с сокетом
socket_clear_error - очищает ошибку на сокете или последний код ошибки
socket_close - закрывает ресурс сокета
socket_connect - инициирует соединение с сокетом
socket_create_listen - открывает сокет на порте для приёма соединений
socket_create_pair - создаёт пару одинаковых сокетов и сохраняет их в fds
socket_create - создаёт сокет (конечный пункт для соединения)
socket_get_option - получает опции сокета
socket_getpeername - запрашивает удалённую сторону данного сокета, что может дать host/port, или путь файловой системы UNIX, в зависимости от типа
socket_getsockname - запрашивает локальную сторону данного сокета, что может дать host/port, или путь файловой системы UNIX, в зависимости от типа
socket_iovec_add - добавляет новый вектор к массиву раздачи/сбора
socket_iovec_alloc - ...]) строит 'struct iovec' для использования с sendmsg, recvmsg, writev и readv
socket_iovec_delete - удаляет вектор из массива векторов
socket_iovec_fetch - возвращает данные, содержащиеся в iovec, специфицированном iovec_id[iovec_position]
socket_iovec_free - освобождает iovec, специфицированный iovec_id
socket_iovec_set - устанавливает данные, содержащиеся в iovec_id[iovec_position], в new_val
socket_last_error - возвращает последнюю ошибку на сокете
socket_listen - прослушивает соединение на сокете
socket_read - читает максимальное количество байт с сокета
socket_readv - читает из fd, используя scatter-gather массив, определённый iovec_id
socket_recv - получает данные из соединённого сокета
socket_recvfrom - получает данные из сокета, соединённого иди нет
socket_recvmsg - используется для получения сообщений на сокете, ориентированном на соединение или нет
socket_select - запускает системный вызов select() на данных массивах сокетов с таймаутом, специфицированным tv_sec и tv_usec
socket_send - отправляет данные в соединённый сокет
socket_sendmsg - отправляет сообщение на сокет, независимо от того, ориентирован он на соединение/connection-oriented или нет
socket_sendto - отправляет сообщение на сокет, независимо от того, соединён он или нет
socket_set_nonblock - устанавливает неблокирующий режим  для дескриптора файла fd
socket_set_option - устанавливает опции сокета
socket_shutdown - отключает приём, отправку с сокета, или и то, и другое
socket_strerror - возвращает строку с описанием ошибки сокета
socket_write - записывает в сокет
socket_writev - записывает в дескриптор файла, fd, используя scatter-gather массив, определённый iovec_id

НазадОглавление Вперёд
snmpwalkoidВверх socket_accept