PHP TCP socket server I created a PHP script which will be running 24/7 as a TCP socket server and will send data from the DB back to clients. The code is working, and so far, I see no problems.

However, I can only test it with one client. The info I need is, what will happen when there will be 100+ clients? Can any of you see any weaknesses in the code? Can I test it somehow?

include('db_con.php');
include('db_functions.php');
error_reporting(E_ALL);

// Allow the script to hang around waiting for connections
set_time_limit(0);

// Turn on implicit output flushing so we see what we're getting as it comes in
ob_implicit_flush();

$address = '10.4.1.6';
$port = 4950;

$failed = 0;

try {
    // Create a socket (AF_INET = IPV4, SOCK_STREAM=TCP stream)
    $failed = 1;
    $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

    // Bind connection to IP/port
    $failed = 2;
    socket_bind($sock, $address, $port);

    $failed = 3;
    socket_listen($sock, SOMAXCONN);

    while (true) {
        // Accept connection
        $failed = 4;
        $client = socket_accept($sock);

        $failed = 6;
        $rec = socket_read($client, 1024);
        $id_d = substr($rec, 0, 1);
        $id = intval(substr($rec, 1, 1));

        // Connect to database and get results
        $failed = 7;

        $failed = 8;
        $data = "ok\r\n";

        if (strcmp($id_d, 'o') == 0) {
            $in_O = returnResultsForTCP_O($db, $id);
            foreach ($in_O as $r) {
                $data .= 'o'
                        . $r['ring_time'] . ' '
                        . ((int) $r['duration'] &lt; 100 ? '0' : '')
                        . $r['duration'] . ' '
                        . $r['bell_mode'] . '\r\n';
            }
        } else {
            $in_D = returnResultsForTCP_D($db, $id);
            $in_W = returnResultsForTCP_W($db, $id);
            foreach ($in_D as $r) {
                $data .= 'd'
                        . $r['ring_time'] . ' '
                        . ((int) $r['duration'] &lt; 100 ? '0' : '')
                        . $r['duration'] . ' '
                        . $r['bell_mode'] . '\r\n';
            }

            foreach ($in_W as $r) {
                $data .= 'w'
                        . $r['ring_time'] . ' '
                        . ((int) $r['duration'] &lt; 100 ? '0' : '')
                        . $r['duration'] . ' '
                        . $r['day'] . ' '
                        . $r['bell_mode'] . '\r\n';
            }
        }

        $failed = 5;
        socket_write($client, $data);
        socket_close($client);
    }
} catch (Exception $e) {
    if ($failed &lt; 6) {
        $causes = array('create', 'bind', 'listen', 'accept', 'write');
        echo 'socket_' . $causes[$failed - 1] . '() failed. Reason: '
                . socket_strerror(socket_last_error($sock)) . '\n';
    } else {
        echo 'Failed at ' . $failed . '\n' . $e . '\n';
    }

    socket_close($sock);
}


The $failed part is just for testing; I'll remake it later (change it so the logs will be written to file - logging).
Here are a few things:

The loop only handles one connection at a time, which could cause some issues for other clients connecting in the future. If returnResultsForTCP_O is slow and blocking, that could even prevent other clients from working.

Two possible solutions include:

Use http://reactphp.org/ to handle the connections

Or if you would still like to handle the connections manually, you can accept many connections at the same time by adding them all to an array and using socket_select to get arrays of all the sockets ready to read from or write to:

http://php.net/manual/en/function.socket-select.php

You would still need to make the database calls non-blocking. Again, reactphp has some database connection libraries available for it. Otherwise you will have to find another way to access the database in a non-blocking way. Although it isn't nonblocking, you can make a secondary php process you open with proc_open and pass the request into. Then just set stream_set_blocking on the proc_open pipe file handles, and read from it in your main loop.