Current Location: Home> Latest Articles> Correct use of socket_set_block in multi-threaded/multi-process PHP service

Correct use of socket_set_block in multi-threaded/multi-process PHP service

gitbox 2025-05-28

When building high-performance PHP server-side services, it is often necessary to use multi-threaded or multi-process models to handle concurrent connections. Socket programming is an important means to achieve this goal. However, when handling Socket connections, the settings of blocking and non-blocking become key. The socket_set_block() and socket_set_nonblock() functions provided by PHP can be used to control this behavior. Using them reasonably can prevent threads or processes from being stuck due to I/O blocking, improving service stability and responsiveness.

This article will introduce how to correctly use the socket_set_block() function in a multi-threaded or multi-process PHP service to avoid blocking problems, and explain its application scenarios and best practices in combination with specific code examples.

1. The difference between blocking and non-blocking Sockets

By default, Socket is blocking. When you call a function like socket_read() or socket_accept() to a blocking Socket, if there is no data to be read or there is no new connection, the call will wait until the condition is satisfied.

This is not a problem in the single-threaded model, but in a multi-threaded or multi-process environment, if a child thread or child process cannot release resources in time due to blockage, it may lead to waste of resources or even the program will be dead.

Non-blocking Sockets will not wait, they will return immediately, and if there is currently no data, an error will be returned (usually EAGAIN or EWOULDBLOCK ). You can get the error code and process it through socket_last_error() .

2. The timing of correct use of socket_set_block()

socket_set_block() is used to set Socket to blocking mode, while its inverse function socket_set_nonblock() is used to set non-blocking mode.

In multithreading or multiprocessing, the recommended strategies are:

  • In the main thread or parent process, the listening Socket adopts a non-blocking mode to avoid accept blocking;

  • In a child thread or child process, a single client connection can be switched to blocking mode to facilitate processing of complete request logic;

  • In event loops or modes using select() and stream_select() , it is recommended to maintain non-blocking mode.

3. Example: Application in multi-process PHP service

Here is an example of a PHP service based on a multi-process model that shows how to correctly use socket_set_block() to avoid blocking problems:

<code> <?php set_time_limit(0);

$host = '0.0.0.0';
$port = 9000;

// Create Socket
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($server, $host, $port);
socket_listen($server);
socket_set_nonblock($server); // Set the main Socket to non-blocking mode

echo "Server started on {$host}:{$port}\n";

while (true) {
$client = @socket_accept($server);

 if ($client === false) {
    usleep(100000); // avoidCPUIdle
    continue;
}

$pid = pcntl_fork();

if ($pid == -1) {
    die("Fork failed\n");
} elseif ($pid == 0) {
    // Subprocess
    socket_close($server); // Subprocess不需要监听Socket

    socket_set_block($client); // Setting up the clientSocketIn blocking mode

    $input = socket_read($client, 1024);
    $output = strtoupper(trim($input));
    socket_write($client, "You said: $output\n");

    socket_close($client);
    exit(0);
} else {
    // Parent process
    socket_close($client); // Parent process不处理客户端Socket
    pcntl_wait($status, WNOHANG); // avoid僵尸进程
}

}
?>
</code>

In this example, the main process uses a non-blocking Socket to wait for connection, avoiding socket_accept() blocking; while in the child process, we switch the Socket that interacts with the client back to blocking mode, which facilitates the sequential processing of input and output, and the logic is simpler and more reliable.

4. Additional suggestions and precautions

  1. Do not set block and nonblock to alternate switching on a Socket at the same time , as this may cause state confusion. It is easier to manage processes or threads that define responsibilities.

  2. Listening to multiple non-blocking Sockets using select() is a more efficient way to fit an event-driven model.

  3. PHP's stream_socket_* series functions provide more friendly encapsulation in some scenarios, and can also be used with stream_set_blocking() to control blocking behavior.

  4. Don't panic when error codes like "Resource temporarily unavailable" appear. This is one of the characteristics of non-blocking Sockets and needs to be resolved through logical retry or event polling.

5. Summary

The rational use of socket_set_block() and socket_set_nonblock() is the key to building efficient PHP network services. Especially in a multi-threaded or multi-process environment, clarifying responsibilities and setting appropriate blocking modes can not only avoid thread/process blocking problems, but also improve service response speed and stability.

Through the above examples and strategies, I believe that you can better use these Socket functions in actual projects to create a robust PHP background service. If you are building a private Git service or real-time communication platform like <code>gitbox.net</code>, precise Socket control is an indispensable part.