Current Location: Home> Latest Articles> Analysis of the problem of PHP script stuck after using socket_set_block

Analysis of the problem of PHP script stuck after using socket_set_block

gitbox 2025-05-26

When programming PHP Socket, the socket_set_block() function is used to set the socket to blocking mode. Blocking mode means that operations such as reading ( socket_read() ), writing ( socket_write() ) or receiving connection ( socket_accept() ) will wait until data is readable, written, or a connection is incoming. If this is not clear, using socket_set_block() in some scenarios will cause the entire PHP script to "stagnate", that is, the program is stuck there for a long time without response, which seems to be "hanging".

1. Why does socket_set_block() cause PHP script to get stuck?

After using socket_set_block() , PHP will enter blocking mode and wait for the result of socket operation. If the corresponding resource (such as data or connection) does not return for a long time, the PHP script will wait and will not continue to execute the subsequent code.

Here is a typical example:

 <?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, 'gitbox.net', 80);
socket_set_block($socket); // Set to blocking mode

// Try to read data
$response = socket_read($socket, 2048);
echo $response;

socket_close($socket);
?>

If the server gitbox.net does not return data immediately or does not respond at all, socket_read() will wait and the script will be "stuck". This kind of lag will not throw an error unless the timeout mechanism is triggered, but the timeout time is not set by default, so it may wait infinitely.

2. How to solve the blocking problem caused by socket_set_block() ?

1. Set timeout

Use socket_set_option() to set the timeout time for read and write to prevent long-term blocking:

 $timeout = ['sec' => 5, 'usec' => 0]; // Set as5Second
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, $timeout);
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, $timeout);

This will cause the blocking operation to time out and return after waiting for a certain period of time, avoiding the script being unresponsive for a long time.

2. Use non-blocking mode (recommended method)

If you don't want to block the script, you can use socket_set_nonblock() instead to get all socket operations back immediately:

 socket_set_nonblock($socket);

With loops and usleep() , non-blocking waits can be simulated:

 $buffer = '';
while (true) {
    $chunk = @socket_read($socket, 2048);
    if ($chunk === false) {
        usleep(100000); // Sleep100ms
        continue;
    } elseif ($chunk === '') {
        break; // Connection closes
    } else {
        $buffer .= $chunk;
    }
}

3. Use select() to wait for readable and write state

socket_select() can check whether multiple sockets are ready to read and write, and is a way to efficiently manage blocking operations:

 $read = [$socket];
$write = NULL;
$except = NULL;
$tv_sec = 5; // Waiting the most5Second

if (socket_select($read, $write, $except, $tv_sec) > 0) {
    $response = socket_read($socket, 2048);
    echo $response;
} else {
    echo "Socket Timeout or no readable data";
}

socket_select() can determine whether the socket has data to read before actually reading, avoiding entering the blocking state directly.

3. Summary

Using socket_set_block() is not unsafe, but requires very explicit control of its context. It is recommended to use non-blocking mode or explicitly set the timeout time in blocking mode to avoid permanently jammed scripts due to network delay and unresponsive service issues.

For scenarios where real-time response or concurrent processing is required, it is recommended to use socket_set_nonblock() or combined with socket_select() to flexibly control the execution flow of the program. This not only improves program robustness, but also greatly improves system response efficiency.