Current Location: Home> Latest Articles> socket_accept() cooperates with socket_set_timeout to implement connection timeout control

socket_accept() cooperates with socket_set_timeout to implement connection timeout control

M66 2025-05-28

In PHP, when programming with native sockets, the socket_accept() function is used to accept client connection requests, but by default, this function is blocking - that is, if there is no client connection, the program will wait and cannot automatically time out. In order to avoid the program being stuck or unresponsive due to waiting for the connection, we can combine socket_set_timeout() to achieve connection timeout control, thereby improving the robustness of the program.

This article will introduce in detail how to use socket_accept() and socket_set_timeout() to implement the function of PHP connection timeout control.

1. Review of basic knowledge

  • socket_accept($socket)
    Waiting for the client connection request blocking, if there is a connection request, a new socket resource will be returned, otherwise it will be blocked.

  • socket_set_timeout($socket, $seconds, $microseconds)
    Sets the timeout time for the specified socket. After the timeout, the read/write operation returns a timeout error.

It should be noted that socket_set_timeout() is a timeout control for read and write operations, and cannot directly control the blocking waiting time of socket_accept() . Therefore, we need to cooperate with other ways (such as non-blocking mode or using socket_select() ) to achieve true connection waiting timeout.

2. Implementation ideas

  1. Set the listening socket to non-blocking mode <br> Calling socket_accept() in this way will not block. If there is no connection request, false will be returned immediately.

  2. Use loop + delay to judge timeout <br> Call socket_accept() repeatedly in the loop. If false is returned, determine whether the timeout is timed out. If the timeout is timed out, the wait will be exited.

  3. Once the connection is received, use socket_set_timeout() to set the read and write timeout <br> Ensure that there is timeout control during subsequent data transmission.

3. Sample code

 <?php
$host = "0.0.0.0";
$port = 12345;
$timeoutSeconds = 10; // Maximum waiting connection time

// create TCP socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
    die("socket_create failed: " . socket_strerror(socket_last_error()) . "\n");
}

// Bind port
if (socket_bind($socket, $host, $port) === false) {
    die("socket_bind failed: " . socket_strerror(socket_last_error($socket)) . "\n");
}

// Listen to port
if (socket_listen($socket, 5) === false) {
    die("socket_listen failed: " . socket_strerror(socket_last_error($socket)) . "\n");
}

// Set up monitoring socket Not blocking
socket_set_nonblock($socket);

$startTime = time();
$clientSocket = false;

echo "Waiting for client connection,Timeout:{$timeoutSeconds}Second\n";

while (true) {
    $clientSocket = @socket_accept($socket);
    if ($clientSocket !== false) {
        echo "Client is connected!\n";
        break;
    }

    // Determine whether the timeout is
    if ((time() - $startTime) >= $timeoutSeconds) {
        echo "Waiting for client connection超时。\n";
        break;
    }

    // Sleep 100ms avoid CPU Too high occupancy
    usleep(100000);
}

if ($clientSocket !== false) {
    // Setting up the client socket Read and write timeout,For example 5 Second
    socket_set_option($clientSocket, SOL_SOCKET, SO_RCVTIMEO, ["sec"=>5, "usec"=>0]);
    socket_set_option($clientSocket, SOL_SOCKET, SO_SNDTIMEO, ["sec"=>5, "usec"=>0]);

    // Example of reading client data
    $buf = '';
    $bytes = socket_recv($clientSocket, $buf, 2048, 0);
    if ($bytes === false) {
        echo "Failed to receive data or timed out:" . socket_strerror(socket_last_error($clientSocket)) . "\n";
    } else {
        echo "Received client data:" . $buf . "\n";
    }

    socket_close($clientSocket);
}

socket_close($socket);
?>

4. Code analysis

  • Non-blocking listening : Use socket_set_nonblock() to avoid socket_accept() blocking, allowing us to customize the timeout logic.

  • Looping to wait for the connection : Each time socket_accept() is called, if there is no connection, it returns false immediately, and determines whether the timeout condition is reached. If the timeout does not expire, continue to wait.

  • Set read and write timeout after connection : Use socket_set_option() to set read and write timeout for the client socket to prevent permanent blocking when subsequent data is read.

  • usleep() Reduce CPU usage : Avoid empty loops causing excessive CPU usage.

5. Summary

By setting the listening socket to non-blocking and combining loop polling to determine the time, the timeout control of socket_accept() blocking waiting connection is achieved. At the same time, after receiving the connection, use socket_set_option() to set the read and write timeout to ensure the stability and security of the data transmission process.

This solution is simple and practical, and is very suitable for PHP server programs that require manual management of socket connection timeouts.