HELP! Socket server w/multiple connections

From: Date: Mon, 26 Apr 2004 20:26:52 +0000
Subject: HELP! Socket server w/multiple connections
Groups: php.general 
Request: Send a blank email to php-general+get-184699@lists.php.net to get a copy of this message
Hi Mike, I'm at a point where a little direction would be really appreciated. I've gone through several tutorials for socket servers and clients. I've got a web form submitting data to my socket server, and it works. I think I even understand what's going on. So far, so good. Now comes the hard part: I need to write a socket server that stays running (easy) and can handle and keep track of multiple connections (hard, for me). Now, I've found several tutorial code snippets, but no matter how much editing I do to them, when I run them from the command line, they don't work. It seems like there is a huge gulf of expertise separating a single-connection socket server with one that handles multiple connections concurrently. And no matter which example I use, I can't get them to run. With the first socket server I tried, I got this error message: PHP Notice: Undefined offset: 0 in /Users/me/Sites/sockets/test/s9.php on line 21 Notice: Undefined offset: 0 in /Users/me/Sites/sockets/test/s9.php on line 21 PHP Notice: Undefined offset: 1 in /Users/me/Sites/sockets/test/s9.php on line 21 Notice: Undefined offset: 1 in /Users/me/Sites/sockets/test/s9.php on line 21 PHP Notice: Undefined offset: 2 in /Users/me/Sites/sockets/test/s9.php on line 21 Here's the code it doesn't like: // Setup clients listen socket for reading $read[0] = $sock; for ($i = 0; $i < $max_clients; $i++) { if ($clients[$i]['sock'] != $null) $read[$i+1] = $clients[$i]['sock']; } Here's the original code, in full: http://www.zend.com/zend/tut/tutorial-staub3.php After struggling with this, I found another multi-connection socket server sample which looks even stronger on paper, but fails to do anything. At the command line, I execute it, and it runs without errors and immediately returns to command line. Here's a link to the code: http://www.zend.com/lists/php-dev/200205/msg00286.html Here's my code verbatim: --------- <?php // VARIABLES set_time_limit(0); error_reporting(E_ALL); // defaults...
define('MAXLINE', 1024);        // how much to read from a socket at a time
define('LISTENQ', 10);          // listening queue
define('PORT', 10000);          // the default port to run on
define('FD_SETSIZE', 5);        // file descriptor set size (max number of concurrent clients)...
// for kill the biatch... function killDaemon() {
    global $listenfd, $client;
    socket_close($listenfd);
    $msg = "Daemon going down!\n";
    for ($i = 0; $i < FD_SETSIZE; $i++)
    {
        if ($client[$i] != null)
        {
            socket_write($client[$i], $msg, strlen($msg));
            socket_close($client[$i]);
        }
    }
    print "Shutting down the daemon\n";
    exit;
} // whenever a client disconnects... function closeClient($i) {
    global $client, $remote_host, $remote_port;
    print "closing client[$i] ({$remote_host[$i]}:{$remote_port[$i]})\n";
    socket_close($client[$i]);
    $client[$i] = null;
    unset($remote_host[$i]);
    unset($remote_port[$i]);
} // set up the file descriptors and sockets... // $listenfd only listens for a connection, it doesn't handle anything // but initial connections, after which the $client array takes over... $listenfd = socket_create(AF_INET, SOCK_STREAM, 0); if ($listenfd)
    print "Listening on port " . PORT . "\n";
else
    die("AIEE -- socket died!\n");
socket_setopt($listenfd, SOL_SOCKET, SO_REUSEADDR, 1); if (!socket_bind($listenfd, "0.0.0.0", PORT)) {
    socket_close($listenfd);
    die("AIEE -- Couldn't bind!\n");
} socket_listen($listenfd, LISTENQ); // set up our clients. After listenfd receives a connection, // the connection is handed off to a $client[]. $maxi is the // set to the highest client being used, which is somewhat // unnecessary, but it saves us from checking each and every client // if only, say, the first two are being used. $maxi = -1; for ($i = 0; $i < FD_SETSIZE; $i++)
    $client[$i] = null;
// the main loop. while(1) {
    $rfds[0] = $listenfd;
    for ($i = 0; $i < FD_SETSIZE; $i++)
    {
        if ($client[$i] != null)
            $rfds[$i + 1] = $client[$i];
    }
    // block indefinitely until we receive a connection...
    $nready = socket_select($rfds, $null, $null, null);
    // if we have a new connection, stick it in the $client array,
    if (in_array($listenfd, $rfds))
    {
        print "listenfd heard something, setting up new client\n";
        for ($i = 0; $i < FD_SETSIZE; $i++)
        {
            if ($client[$i] == null)
            {
                $client[$i] = socket_accept($listenfd);
                socket_setopt($client[$i], SOL_SOCKET, SO_REUSEADDR, 1);
                socket_getpeername($client[$i], $remote_host[$i],
$remote_port[$i]);
                print "Accepted {$remote_host[$i]}:{$remote_port[$i]} as
client[$i]\n";
                break;
            }
            if ($i == FD_SETSIZE - 1)
            {
                trigger_error("too many clients", E_USER_ERROR);
                exit;
            }
        }
        if ($i $maxi)
            $maxi = $i;
        if (--$nready <= 0)
            continue;
    }
    // check the clients for incoming data.
    for ($i = 0; $i <= $maxi; $i++)
    {
        if ($client[$i] == null)
            continue;
        if (in_array($client[$i], $rfds))
        {
            $n = trim(socket_read($client[$i], MAXLINE));
            if (!$n)
                closeClient($i);
            else
            {
                // if a client has sent some data, do one of these:
                if ($n == "/killme")
                    killDaemon();
                else if ($n == "/quit")
                    closeClient($i);
                else
                {
                    // print something on the server, then echo the incoming
                    // data to all of the clients in the $client array.
                    print "From {$remote_host[$i]}:{$remote_port[$i]},
client[$i]: $n\n";
                    for ($j = 0; $j <= $maxi; $j++)
                    {
                        if ($client[$j] != null)
                            socket_write($client[$j], "From client[$i]:
$n\r\n");
                    }
                }
            }
            if  (--$nready <= 0)
                break;
        }
    }
} ?> Any ideas???

« previous php.general (#184699) next »