Current Location: Home> Latest Articles> How to Efficiently Handle Concurrent Requests with the socket_set_blocking Function in PHP

How to Efficiently Handle Concurrent Requests with the socket_set_blocking Function in PHP

gitbox 2025-06-09

When handling high-concurrency requests, PHP, as a server-side scripting language, often faces the issue of blocking, especially when a large number of I/O operations (such as network requests, file reading and writing, etc.) are involved. The socket_set_blocking function in PHP is a useful tool that helps developers efficiently control the blocking behavior of sockets, thereby improving the ability to handle concurrent requests. This article will introduce how to use the socket_set_blocking function to optimize PHP's concurrent request handling.

Overview of the socket_set_blocking Function

The socket_set_blocking function is used to control whether a socket operates in blocking mode. By default, a socket operates in blocking mode, meaning that when a socket operation (such as reading or writing data) occurs without data being available, the program will wait until the data is available. By setting the socket to non-blocking mode, the program can continue executing other tasks instead of waiting for the completion of a particular I/O operation.

Function Definition:

bool socket_set_blocking ( resource $socket , bool $blocking )
  • $socket: The socket resource to be configured.

  • $blocking: If true, the socket will be set to blocking mode; if false, the socket will be set to non-blocking mode.

How to Use socket_set_blocking to Improve Concurrency Performance

When handling a large number of concurrent requests, the traditional blocking mode can cause performance bottlenecks. By setting the socket to non-blocking mode, PHP scripts can continue processing other requests while waiting for a socket operation to complete. Below are ways to achieve efficient concurrent request handling using socket_set_blocking:

1. Basic Code Example

Suppose we need to handle multiple client requests and want to avoid blocking when processing each request. Here is a simple example:

<?php  
// Create TCP socket  
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);  
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
<p>// Bind the socket<br>
socket_bind($socket, '127.0.0.1', 8080);</p>
<p>// Start listening<br>
socket_listen($socket);</p>
<p>// Set to non-blocking mode<br>
socket_set_blocking($socket, false);</p>
<p>while (true) {<br>
// Accept client connection<br>
$client = socket_accept($socket);</p>
<pre class="overflow-visible!"><div class="contain-inline-size rounded-2xl border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary"><div class="flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none rounded-t-2xl">swift</div><div class="sticky top-9"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-sidebar-surface-primary text-token-text-secondary dark:bg-token-main-surface-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"><button class="flex gap-1 items-center select-none py-1" aria-label="复制"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-xs"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>复制</button><button class="flex items-center gap-1 py-1 select-none"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-xs"><path d="M2.5 5.5C4.3 5.2 5.2 4 5.5 2.5C5.8 4 6.7 5.2 8.5 5.5C6.7 5.8 5.8 7 5.5 8.5C5.2 7 4.3 5.8 2.5 5.5Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M5.66282 16.5231L5.18413 19.3952C5.12203 19.7678 5.09098 19.9541 5.14876 20.0888C5.19933 20.2067 5.29328 20.3007 5.41118 20.3512C5.54589 20.409 5.73218 20.378 6.10476 20.3159L8.97693 19.8372C9.72813 19.712 10.1037 19.6494 10.4542 19.521C10.7652 19.407 11.0608 19.2549 11.3343 19.068C11.6425 18.8575 11.9118 18.5882 12.4503 18.0497L20 10.5C21.3807 9.11929 21.3807 6.88071 20 5.5C18.6193 4.11929 16.3807 4.11929 15 5.5L7.45026 13.0497C6.91175 13.5882 6.6425 13.8575 6.43197 14.1657C6.24513 14.4392 6.09299 14.7348 5.97903 15.0458C5.85062 15.3963 5.78802 15.7719 5.66282 16.5231Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M14.5 7L18.5 11" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>编辑</button></div></div></div><div class="overflow-y-auto p-4" dir="ltr">// If no connection, continue executing other tasks  
if ($client === false) {  
    // For example, check other tasks or log actions  
    echo "No client connection, continuing with other tasks...\n";  
    continue;  
}

// Set client to non-blocking mode  
socket_set_blocking($client, false);

// Read client data  
$input = socket_read($client, 1024);

if ($input) {  
    echo "Received data from client: $input\n";  
    // Process request and respond  
    socket_write($client, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nHello, Client!");  
}

// Close connection  
socket_close($client);  

}

socket_close($socket);
?>

2. Understanding Non-Blocking Mode

In the above code, we set the server-side socket to non-blocking mode using socket_set_blocking($socket, false). This means that when no client request is received, socket_accept will not block waiting, but will return false. This allows the program to continue executing other tasks without being stuck on socket_accept when there is no client connection.

Similarly, when handling each client connection, we also set the client socket to non-blocking mode. This way, when reading data, the program does not get stuck, thus improving the ability to handle concurrent requests.

3. Efficient Handling of Concurrent Requests

In high-concurrency scenarios, by using non-blocking socket operations, you can more efficiently handle multiple concurrent requests using socket_select or multi-threading/multi-processing techniques. socket_select is a very useful function that can monitor multiple socket resources, ensuring that only readable sockets are processed, thus avoiding unnecessary blocking.

Example: Using socket_select to Handle Multiple Sockets

<?php  
// Create master socket  
$masterSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);  
socket_set_option($masterSocket, SOL_SOCKET, SO_REUSEADDR, 1);  
socket_bind($masterSocket, '127.0.0.1', 8080);  
socket_listen($masterSocket);
<p>// Set to non-blocking mode<br>
socket_set_blocking($masterSocket, false);</p>
<p>$clients = array($masterSocket);</p>
<p>while (true) {<br>
// Use socket_select to monitor<br>
$read = $clients;<br>
$write = null;<br>
$except = null;</p>
<pre class="overflow-visible!"><div class="contain-inline-size rounded-2xl border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary"><div class="flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none rounded-t-2xl">php</div><div class="sticky top-9"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-sidebar-surface-primary text-token-text-secondary dark:bg-token-main-surface-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"><button class="flex gap-1 items-center select-none py-1" aria-label="复制"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-xs"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>复制</button><button class="flex items-center gap-1 py-1 select-none"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-xs"><path d="M2.5 5.5C4.3 5.2 5.2 4 5.5 2.5C5.8 4 6.7 5.2 8.5 5.5C6.7 5.8 5.8 7 5.5 8.5C5.2 7 4.3 5.8 2.5 5.5Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M5.66282 16.5231L5.18413 19.3952C5.12203 19.7678 5.09098 19.9541 5.14876 20.0888C5.19933 20.2067 5.29328 20.3007 5.41118 20.3512C5.54589 20.409 5.73218 20.378 6.10476 20.3159L8.97693 19.8372C9.72813 19.712 10.1037 19.6494 10.4542 19.521C10.7652 19.407 11.0608 19.2549 11.3343 19.068C11.6425 18.8575 11.9118 18.5882 12.4503 18.0497L20 10.5C21.3807 9.11929 21.3807 6.88071 20 5.5C18.6193 4.11929 16.3807 4.11929 15 5.5L7.45026 13.0497C6.91175 13.5882 6.6425 13.8575 6.43197 14.1657C6.24513 14.4392 6.09299 14.7348 5.97903 15.0458C5.85062 15.3963 5.78802 15.7719 5.66282 16.5231Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M14.5 7L18.5 11" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>编辑</button></div></div></div><div class="overflow-y-auto p-4" dir="ltr">// Monitor sockets  
if (socket_select($read, $write, $except, null) > 0) {  
    // Iterate through all sockets with data  
    foreach ($read as $socket) {  
        if ($socket === $masterSocket) {  
            // Accept new connection  
            $client = socket_accept($masterSocket);  
            socket_set_blocking($client, false);  
            $clients[] = $client;  
        } else {  
            // Read client data  
            $input = socket_read($socket, 1024);  
            if ($input === false) {  
                // Disconnect  
                socket_close($socket);  
                $clients = array_diff($clients, array($socket));  
            } else {  
                echo "Received data: $input\n";  
                socket_write($socket, "Hello, Client!");  
            }  
        }  
    }  
}  

}

socket_close($masterSocket);
?>

In this example, the socket_select function is used to simultaneously monitor multiple socket connections. When a socket is available, the program reads data and processes it. This way, the server can handle multiple concurrent requests without one request blocking the processing of others.

Conclusion

Using the socket_set_blocking function to set sockets to non-blocking mode is an important method to improve PHP's ability to handle concurrent requests. By properly configuring the blocking mode and using functions like socket_select, developers can implement efficient concurrent request handling in PHP, avoiding performance bottlenecks caused by traditional blocking modes. Optimizing I/O operations is key to improving performance for applications that need to handle a large number of concurrent connections.