A listening socket blocks at socket_accept() until a client connects unless it is placed in non-blocking mode. For a worker that also performs other tasks, set the socket non-blocking and wait with socket_select() before accepting a client.
Last updated: October 19, 2026.
<?php
$listener = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($listener === false) {
throw new RuntimeException(socket_strerror(socket_last_error()));
}
socket_set_option($listener, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($listener, '127.0.0.1', 9000);
socket_listen($listener);
socket_set_nonblock($listener);
$read = [$listener];
$write = [];
$except = [];
$ready = socket_select($read, $write, $except, 1);
if ($ready === false) {
throw new RuntimeException(socket_strerror(socket_last_error()));
}
if ($ready > 0 && ($client = socket_accept($listener)) !== false) {
socket_write($client, "Connected\n");
socket_close($client);
}
socket_close($listener);The one-second timeout lets the process regain control even when nobody connects. In a long-running server, place the readiness check inside the application loop and keep the listener open until shutdown.
Use the socket API consistently
The PHP manual documents socket_set_nonblock() for a Socket returned by socket_create(). Do not pass that object to stream_set_blocking() or its alias socket_set_blocking(); those functions operate on stream resources.
On a blocking listener, socket_accept() waits for a pending connection. On a non-blocking listener it can return false when no connection is ready. Waiting for readability first prevents a normal idle period from being logged repeatedly as an application error.
Treat readiness and acceptance as separate checks
The socket_select() result may be zero for a timeout, a positive count for ready sockets, or false for failure. A ready listener can still fail during socket_accept(), so production code should test both calls and log the numeric error with its socket_strerror() message.
Set timeouts, connection limits, and maximum request sizes for every accepted client. Close a client in a finally block when later processing can throw, and avoid doing slow work in the accept loop. Hand accepted sockets to bounded workers or an event loop instead.
Continue with detecting PHP socket timeouts, using Unix sockets with cURL, and debugging PHP with Xdebug.