Поиск…


Соединитель TCP-клиента

Создание сокета, использующего TCP (протокол управления передачей)

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

Убедитесь, что сокет успешно создан. Функция onSocketFailure исходит из примера ошибок сокетов обработки в этом разделе.

if(!is_resource($socket)) onSocketFailure("Failed to create socket");

Подключите разъем к указанному адресу

Вторая строка изящно выходит из строя, если соединение не выполнено.

socket_connect($socket, "chat.stackoverflow.com", 6667)
        or onSocketFailure("Failed to connect to chat.stackoverflow.com:6667", $socket);

Отправка данных на сервер

Функция socket_write отправляет байты через сокет. В PHP байтовый массив представлен строкой, которая обычно нечувствительна к кодированию.

socket_write($socket, "NICK Alice\r\nUSER alice 0 * :Alice\r\n");

Получение данных с сервера

Следующий фрагмент получает некоторые данные с сервера, используя функцию socket_read .

Передача PHP_NORMAL_READ в качестве третьего параметра считывается до байта \r / \n , и этот байт включен в возвращаемое значение.

Передача PHP_BINARY_READ , напротив, считывает требуемый объем данных из потока.

Если socket_set_nonblock был вызван перед и PHP_BINARY_READ используется, socket_read вернет false немедленно. В противном случае метод блокируется до тех пор, пока не будут получены достаточные данные (чтобы достичь длины во втором параметре или достичь окончания строки), или сокет будет закрыт.

В этом примере читаются данные с предположительно IRC-сервера.

while(true) {
    // read a line from the socket
    $line = socket_read($socket, 1024, PHP_NORMAL_READ);
    if(substr($line, -1) === "\r") {
        // read/skip one byte from the socket
        // we assume that the next byte in the stream must be a \n.
        // this is actually bad in practice; the script is vulnerable to unexpected values
        socket_read($socket, 1, PHP_BINARY_READ);
    }

    $message = parseLine($line);
    if($message->type === "QUIT") break;
}

Закрытие гнезда

Закрытие сокета освобождает сокет и связанные с ним ресурсы.

socket_close($socket);

Разъем TCP-сервера

Создание гнезда

Создайте сокет, который использует TCP. Это то же самое, что и создание клиентского сокета.

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

Соединительная муфта

Свяжите соединения из заданной сети (параметр 2) для определенного порта (параметр 3) в гнездо.

Второй параметр обычно "0.0.0.0" , который принимает соединение из всех сетей. Он также может

Одной из распространенных причин ошибок socket_bind является то, что указанный адрес уже связан с другим процессом . Другие процессы обычно убивают (обычно вручную, чтобы предотвратить случайное убийство критических процессов), чтобы сокеты были освобождены.

socket_bind($socket, "0.0.0.0", 6667) or onSocketFailure("Failed to bind to 0.0.0.0:6667");

Установите сокет для прослушивания

Сделать сокет прослушивать входящие соединения с помощью socket_listen . Второй параметр - это максимальное количество подключений для обеспечения очереди до их принятия.

socket_listen($socket, 5);

Обработка соединения

Сервер TCP фактически является сервером, который обрабатывает дочерние соединения. socket_accept создает новое дочернее соединение.

$conn = socket_accept($socket);

Передача данных для соединения из socket_accept такая же, как и для клиентского сокета TCP .

Когда это соединение должно быть закрыто, вызовите socket_close($conn); непосредственно. Это не повлияет на исходный сокет TCP-сервера.

Закрытие сервера

С другой стороны, socket_close($socket); следует вызывать, когда сервер больше не используется. Это также освободит TCP-адрес, позволяя другим процессам связываться с адресом.

Обработка ошибок сокетов

socket_last_error может использоваться для получения идентификатора ошибки последней ошибки из расширения сокетов.

socket_strerror может использоваться для преобразования идентификатора в удобочитаемые строки.

function onSocketFailure(string $message, $socket = null) {
    if(is_resource($socket)) {
        $message .= ": " . socket_strerror(socket_last_error($socket));
    }
    die($message);
}

Разъем UDP-сервера

Сервер UDP (протокол пользовательских дейтаграмм), в отличие от TCP, не основан на потоках. Он основан на пакетах, т.е. клиент отправляет данные в единицы, называемые «пакеты» на сервер, и клиент идентифицирует клиентов по их адресу. Нет встроенной функции, которая связывает разные пакеты, отправленные с одного и того же клиента (в отличие от TCP, где данные от одного и того же клиента обрабатываются определенным ресурсом, созданным socket_accept ). Можно думать, что новое TCP-соединение принимается и закрывается каждый раз, когда приходит пакет UDP.

Создание гнезда UDP-сервера

$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);

Связывание сокета с адресом

Параметры те же, что и для TCP-сервера.

socket_bind($socket, "0.0.0.0", 9000) or onSocketFailure("Failed to bind to 0.0.0.0:9000", $socket);

Отправка пакета

Эта строка отправляет $data в пакете UDP в $address : $port .

socket_sendto($socket, $data, strlen($data), 0, $address, $port);

Получение пакета

Следующий фрагмент пытается управлять пакетами UDP с индексированным клиентом образом.

$clients = [];
while (true){
    socket_recvfrom($socket, $buffer, 32768, 0, $ip, $port) === true
            or onSocketFailure("Failed to receive packet", $socket);
    $address = "$ip:$port";
    if (!isset($clients[$address])) $clients[$address] = new Client();
    $clients[$address]->handlePacket($buffer);
}

Закрытие сервера

socket_close может использоваться на ресурсе сокета сервера UDP. Это освободит UDP-адрес, позволяя другим процессам связываться с этим адресом.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow