When using sockets for network programming in PHP, non-blocking mode can improve concurrent processing capabilities and is the key to implementing event-driven or multiplexed servers. However, sometimes we need to temporarily set the socket to blocking state to complete certain "must wait" operations, such as reading a large data packet in full, or waiting for the client to send complete handshake data.
Fortunately, PHP provides two functions: socket_set_block() and socket_set_nonblock() , which can easily switch between blocking and non-blocking modes.
This article will combine a specific TCP server example to demonstrate how to temporarily switch the socket to a blocking state in non-blocking listening and restore the non-blocking state after completing the operation.
We build a non-blocking TCP server, listen to the client connection, and after receiving the client connection, we temporarily switch the connection to blocking mode, read a piece of data from the client, and then switch back to non-blocking mode after completion.
Here is the complete code:
<code> <?php $host = '0.0.0.0';
$port = 12345;
// Create socket
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
// Binding and listening
socket_bind($server, $host, $port);
socket_listen($server);
// Set to non-blocking
socket_set_nonblock($server);
echo "Server listening on {$host}:{$port} ...\n";
$clients = [];
while (true) {
// Accept connection (non-blocking)
$client = @socket_accept($server);
if ($client !== false) {
echo "New client connected.\n";
// Add to client list
$clients[] = $client;
// Set the client to non-blocking
socket_set_nonblock($client);
}
foreach ($clients as $index => $sock) {
$buffer = '';
// Temporarily set to block to ensure full read(For example, read a fixed length or until a flag)
socket_set_block($sock);
$bytes = @socket_recv($sock, $buffer, 1024, MSG_DONTWAIT);
// Revert to non-blocking
socket_set_nonblock($sock);
if ($bytes === false || $bytes === 0) {
// Client disconnected
echo "Client disconnected.\n";
socket_close($sock);
unset($clients[$index]);
continue;
}
// Output read data
echo "Received: " . trim($buffer) . "\n";
// Sample response
$response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nHello from server!\n";
socket_write($sock, $response);
}
// Slight delay avoidance CPU Full
usleep(100000);
}
socket_close($server);
?>
</code>
In the above code, our listening socket ($server) is non-blocking and therefore does not block on socket_accept() . Whenever a new connection is accepted, we set the new client to non-blocking too. However, in the part where we process the receiving data, we actively switch the client socket to blocking mode, because we want to ensure that socket_recv() can fully receive the data we expect and avoid data incompleteness.
This is a very common mixed use method and is especially important in many scenarios (such as the protocol handshake phase). For example, you have designed a simple protocol that stipulates that the client must contain fixed header information for the first time, and the server needs to receive it completely before it can continue processing. At this time, using blocking reading becomes very meaningful.
Be cautious when switching modes : using blocking reading temporarily in non-blocking processes is a "forced wait" method. Although it is convenient, if the client does not send any data, the server will be stuck. It is recommended to match the timeout mechanism or the preset data length.
Suitable for short-term blocking : This type of mode switching is suitable for situations where certain operations must be blocked and it is not recommended to use blocking throughout the communication process.
Use socket_set_block() and socket_set_nonblock() to make your PHP socket programming more flexible. You can flexibly select the appropriate blocking mode according to the processing logic, thus taking into account efficiency and integrity.
For more socket programming practices and examples, please refer to the documentation or visit our resource platform: