Socket accept: примеры (PHP)
socket_accept(resource socket): resource|falseФункция socket_accept() принимает входящее соединение на сокете, который был предварительно создан и переведен в режим прослушивания с помощью socket_listen(). Она используется в серверных сетевых приложениях на PHP для обработки множественных клиентских подключений.
- socket (обязательный) - ресурс сокета, созданный
socket_create()и переведенный в режим ожиданияsocket_listen(). - timeout (опциональный, доступен с PHP 8.0) - время ожидания в секундах для операции accept. Если не указан, функция работает в блокирующем режиме.
Функция возвращает новый ресурс сокета для общения с клиентом или false при ошибке.
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '127.0.0.1', 8080);
socket_listen($socket);
// Блокирующее ожидание подключения
$client = socket_accept($socket);
if ($client !== false) {
socket_write($client, "Hello from server!\n");
socket_close($client);
}
socket_close($socket);// Результат: клиент получает строку "Hello from server!"
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ['sec' => 5, 'usec' => 0]);
socket_bind($socket, '0.0.0.0', 9000);
socket_listen($socket);
// Ожидание 3 секунды
$client = socket_accept($socket, 3);
if ($client === false) {
echo "Таймаут подключения\n";
} else {
socket_write($client, "Connected!\n");
}
socket_close($socket);// Если подключение не произошло за 3 секунды: // Таймаут подключения
stream_socket_accept() - функция потоков, работающая с потоковыми ресурсами. Позволяет использовать контексты потоков и неблокирующие операции через stream_set_blocking(). Часто используется в веб-серверах и более высокоуровневых библиотеках.
<?php
$server = stream_socket_server('tcp://127.0.0.1:8081');
$client = stream_socket_accept($server);Socket\select() (из расширения sockets в PHP 8+) - мультиплексирование нескольких сокетов. Позволяет отслеживать несколько сокетов одновременно, что полезно для асинхронных операций.
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 8080))
server.listen()
client, addr = server.accept() # Возвращает кортеж (сокет, адрес)
client.send(b'Hello')
client.close()const net = require('net');
const server = net.createServer();
server.on('connection', (socket) => {
socket.write('Hello');
socket.end();
});
server.listen(8080);ln, _ := net.Listen("tcp", ":8080")
conn, _ := ln.Accept() // Возвращает net.Conn
conn.Write([]byte("Hello\n"))
conn.Close()Ключевое отличие PHP - необходимость предварительной настройки сокета через отдельные вызовы (create, bind, listen), тогда как в других языках часто используются более высокоуровневые API.
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '127.0.0.1', 8080);
// Пропущен socket_listen()
$client = socket_accept($socket); // Ошибка!Warning: socket_accept(): unable to accept incoming connection
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 8080);
socket_listen($socket);
// Блокирует выполнение скрипта до подключения
$client = socket_accept($socket);
// Дальнейший код не выполняется<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '127.0.0.1', 8080);
socket_listen($socket);
socket_close($socket);
$client = socket_accept($socket); // Неверный ресурсWarning: socket_accept() expects parameter 1 to be resource, bool given
- Добавлен необязательный параметр timeout, позволяющий установить время ожидания подключения в секундах.
- Расширение sockets стало частью ядра PHP (ранее требовалась отдельная компиляция).
- Улучшена обработка ошибок - многие функции теперь выбрасывают исключения вместо генерации предупреждений.
<?php
// Новый параметр timeout в PHP 8+
$client = socket_accept($socket, 5.5); // Ожидание 5.5 секунд<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 9999);
socket_listen($socket);
while (true) {
$client = socket_accept($socket);
$pid = pcntl_fork();
if ($pid == 0) {
// Дочерний процесс обрабатывает клиента
socket_write($client, "PID: " . getmypid() . "\n");
sleep(2); // Имитация обработки
socket_close($client);
exit(0);
}
socket_close($client); // Закрываем в родительском процессе
}
socket_close($socket);<?php
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_nonblock($server);
socket_bind($server, '127.0.0.1', 8888);
socket_listen($server);
$clients = [$server];
while (true) {
$read = $clients;
$write = $except = null;
if (socket_select($read, $write, $except, 0) > 0) {
if (in_array($server, $read)) {
$client = socket_accept($server);
$clients[] = $client;
socket_write($client, "Welcome!\n");
}
// Обработка клиентских сокетов...
}
usleep(100000); // 100ms
}<?php
declare(strict_types=1);
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 7777);
socket_listen($socket);
$start = microtime(true);
// Пытаемся принять соединение 2 секунды
while (microtime(true) - $start < 2.0) {
$client = socket_accept($socket, 0.5); // Проверка каждые 500ms
if ($client !== false) {
$peer = '';
socket_getpeername($client, $peer);
echo "Подключен клиент: $peer\n";
socket_close($client);
break;
}
echo "."; // Индикатор ожидания
}
if ($client === false) {
echo "\nКлиенты не подключились за отведенное время\n";
}
socket_close($socket);...... // Если клиент подключился: // Подключен клиент: 127.0.0.1:54321 // Если не подключился: // Клиенты не подключились за отведенное время