Never try to do something as complicated as attach some source to a mailing 
list post after two beer and a hefty lunch. 

Attachment is really here this time.

J



J Smith wrote:

> 
> Speaking of the FD_* macros and such, I'm trying to visualize how to
> re-write some code that I have that relies on the socket_fd_* functions.
> If you get the chance, could you look over this simplified version of what
> I'm doing and point me towards the proper direction to get it working with
> the new API. I want to have this stuff ready when PHP 4.2 or 4.3 come out,
> and seeing as you're the one closest to the sockets extension, I thought
> you could give me some pointers as to how it would work with the abscence
> of the sockets_fd_* functions. (I'm a little confused what to do without
> the FD_* stuff. This could make for a good example in the documentation,
> anyways, if it works as hoped.)
> 
> Attached is the stripped-down source.
> 
> J
> 
> 
#!/usr/local/bin/php -q
<?php

set_time_limit(0);


// defaults...

define('MAXLINE', 1024);        // how much to read from a socket at a time
define('LISTENQ', 10);          // listening queue
$PORT = 10000;                  // the default port to run on
$FD_SETSIZE = 5;               // file descriptor set size (max number of concurrent clients)...


// for kill the biatch...

function killDaemon()
{
    global $listenfd, $client, $FD_SETSIZE;

    socket_close($listenfd);
    $msg = "Daemon going down!\n";
    for ($i = 0; $i < $FD_SETSIZE; $i++)
    {
        if ($client[$i] != -1)
        {
            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 $allset, $client, $isAdmin, $remote_host, $remote_port;

    print "closing client[$i]\n";

    socket_fd_clear($allset, $client[$i]);
    socket_close($client[$i]);
    $client[$i] = -1;
    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...

$allset = socket_fd_alloc();
$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 = -1;
for ($i = 0; $i < $FD_SETSIZE; $i++)
    $client[$i] = -1;

socket_fd_zero($allset);



// the main loop. 

while(1)
{
    socket_fd_set($allset, $listenfd);
    for ($i = 0; $i < $FD_SETSIZE; $i++)
    {
        if ($client[$i] != -1)
            socket_fd_set($allset, $client[$i]);
    }


    // block indefinitely until we receive a connection...

    $nready = socket_select($allset, null, null, null);


    // if we have a new connection, stick it in the $client array,

    if (socket_fd_isset($allset, $listenfd))
    {
        for ($i = 0; $i < $FD_SETSIZE; $i++)
        {
            if ($client[$i] < 0)
            {
                $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] < 0)
            continue;

        if (socket_fd_isset($allset, $client[$i]))
        {
            $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] != -1)
                            socket_write($client[$j], "From client[$i]: $n\r\n");
                    }
                }
            }

            if  (--$nready <= 0)
                break;
        }
    }
}

?>

-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to