Writing Socket Servers in PHP

August 27, 2003

Tutorials

Intended Audience

Prerequisites

Overview – What is a socket server?

•  Types of Sockets

PHP Socket functions

•  Creating a Socket in PHP

•  The making of a real server

•  Practical Uses

•  Security

•  One at a time please

Possible Additions and Improvements

About the Author


Intended Audience

This tutorial is intended for the PHP programmer interested in
exploring the use of PHP Sockets functions to create an Internet Socket
Server.





Prerequisites


This tutorial uses the following:

  • PHP Sockets library. The extension is enabled at compile time using the --enable-sockets
    configure option.
  • CLI (Command Line Interface) version of PHP: enables the running of the socket server from the
    command line.



    As of PHP 4.3.0 the CLI executable is compiled and installed by default (you can explicitly install
    the CLI version by specifying --enable-cli at compile time).
  • Linux OS


Although this tutorial uses Linux, the sockets library operates equally well in Windows
and *nix environments.



In Windows, PHP Sockets can be activated by un-commenting
extension=php_sockets.dll in php.ini





Overview – What is a socket server?


A socket server is a service assigned to a particular port
that listens to incoming requests and responds to them.


Email servers (POP3, SMTP) and web servers are good examples
of socket servers. An HTTP (web) server listens on port 80 to incoming requests
and serves back HTML and other files (images, documents etc).



Socket Servers normally run continuously as a service or a daemon.





Types of Sockets


When information is sent across the Internet, it is usually
split into packets. This allows the sending of large files in many smaller
pieces of information to be later assembled on the other end.



There are two different protocols for splitting the
information into packets, depending on the information type being sent and
delivery requirements.

  • TCP (Transmission Control Protocol) – the
    transmitted packets are numbered and are assembled on the other end, they are
    assembled in order to form the entire message. TCP usually runs over IP
    (Internet Protocol) hence the term TCP/IP.


    TCP ensures that no data is
    lost (if a packet is lost it will be re-transmitted), and is therefore well
    suited for sending images, files or other information that must be received
    whole and integral (like your email).

  • UDP (User Datagram Protocol) – this is a connectionless protocol. Like TCP it can
    run over the IP protocol. The difference is that UDP provides few error recovery
    services and so there is no guarantee that a particular packet will be received
    on the other side, or in what order the packets will be received.



    UDP is particularly suitable for streaming data such as music streams (if we lose some
    information, there is no point in trying to get it again as we may have already
    played that part).

In this tutorial, TCP sockets will be used to ensure that all the data is received intact.
The examples used in this tutorial can be easily converted to use UDP packets.





PHP Socket functions


PHP is well equipped to handle sockets at the lower level. As
of PHP3, PHP had introduced socket handling in the form of
fsockopen() and other associated
functions (see the Network part of the PHP manual at

http://www.php.net/network). As of
PHP4, PHP’s socket functionality was greatly improved with the introduction of
low-level interface to BSD style sockets.



Note: the socket functions in PHP are still marked as
experimental and hence are subject to change in future releases of PHP. Testing
shows they are fairly stable when used in well-written applications.





Creating a Socket in PHP


Creating a low-level socket in PHP is very similar to using
socket functions in C and Unix socket programming. The manual at
http://www.php.net/sockets outlines the
available functions and also points to the Unix Socket FAQ, which is a great
resource on socket programming (although it can take a little while to plough
through the whole thing).



Let’s start with a simple example: a socket server that
listens to a connection on port 9000, accepts a string as input, and returns it
with all white spaces removed.


Quick note about port numbers. Port numbers under 1024 require
root privilege to be able to open them (or Administrator privileges in Windows
NT/2000). They are also mostly reserved for well-established services (such as
HTTP, POP3, SMTP, FTP etc). For ease of use and security, most user-programmed
services listen on port numbers over 1024 (maximum port number available is
65536 as IPV4 has a maximum of quantity of 16 bits).


#!/usr/local/bin/php –q




<?php

// Set time limit to indefinite execution

set_time_limit (0);

// Set the ip and port we will listen on

$address = '192.168.0.100';

$port = 9000;

// Create a TCP Stream socket

$sock = socket_create(AF_INET, SOCK_STREAM, 0);

// Bind the socket to an address/port

socket_bind($sock, $address, $port) or die('Could not bind to address');

// Start listening for connections

socket_listen($sock);

/* Accept incoming requests and handle them as child processes */

$client = socket_accept($sock);

// Read the input from the client &#8211; 1024 bytes

$input = socket_read($client, 1024);

// Strip all white spaces from input

$output = ereg_replace("[ \t\n\r]","",$input).chr(0);

// Display output back to client

socket_write($client, $output);

// Close the client (child) socket

socket_close($client);

// Close the master sockets

socket_close($sock);

?>



In order to run the program, make sure that the
first line #!/usr/local/bin/php –q is the location of the PHP CLI (or CGI) binary.
You will need to change the mode so it is executable (chmod 755 socket_server.php
where socket_server.php is the name of the file) and run it using
./socket_server.php from the command
line.




Now let’s look at each line in detail:


  • #!/usr/local/bin/php –q Executes the php CLI binary with the quiet options so it
    does not print HTTP headers.
  • $sock = socket_create(AF_INET, SOCK_STREAM, 0)
    – Creates the “master” socket. This socket will not serve the clients, rather it will listen to
    incoming requests and spawn new sockets for these clients. It acts a master
    socket “listener”.



    From the PHP manual
    (http://www.php.net/socket_create):
    AF_INET is the domain type of IPV4 protocol – used for TCP and UDP.
    SOCK_STREAM provides sequenced, reliable, full-duplex, connection-based byte streams.
    The TCP protocol is based on this connection type.


Note: to get a UDP type
socket, just replace SOCK_STREAM with
SOCK_DGRAM.

  • socket_bind($sock, $address, $port) or die('Could not bind to address') – Binds
    the socket to the given address and port.
  • socket_listen($sock) – Listens on the given port to the incoming connections,
    once a connection is made, it will be used to create the spawned socket.
  • $client = socket_accept($sock) – Accepts the connection on the master socket.
  • $input = socket_read($client, 1024) – Reads from the accepted socket,
    1024 bytes at a time (or until a \r, \n or \0 is received – depending on the value of the optional
    third parameter – see note below).


Note: The third type parameter to
socket_read() can either be
PHP_BINARY_READ, which uses the system
read() and is safe for reading binary
data (default type as of PHP >= 4.1.0) or
PHP_NORMAL_READ in which reading stops
at \n or \r (default in PHP <= 4.0.6)


  • $output = ereg_replace("[ \t\n\r]","",$input).chr(0) – Removes all white
    space characters using a regular expression.

The one item of interest is chr(0), which represents the null character. This is appended
to the end of the string that will be sent to the user. The reason for terminating the output with the null
character is that quite a few client socket APIs use this character to notify the client of
end of transmission (this is also true of the Macromedia Flash XMLSocket API).

  • socket_write($client, $output) – Writes the output to the client.
  • Finally, socket_close($client) and socket_close($sock)
    Closes the client and master socket.



The making of a real server


Now that you know the basic steps required to set up a socket
and listen to an incoming request, you are ready to create a full-fledged
server.



Note that in the code above, the program is run once, awaits
an incoming connection and then exits. That is fine for explaining the steps
required to create a socket server, but it is unsuitable for real world
situations. Once your program runs and responds to an incoming request, you do
not want it to exit (meaning you have to restart it).



We therefore need a mechanism to run the program continuously
– enter the loop.



We can use a while(true) { /* do something */ } to cause the program to run continuously
until we issue an explicit exit statement.




We will expand on the above example, adding the following functionality:


  • allow the program to run endlessly
  • create termination facilities
  • provide for the simultaneous handling of multiple clients


#!/usr/local/bin/php –q




<?php

// Set time limit to indefinite execution

set_time_limit (0);

// Set the ip and port we will listen on

$address = '192.168.0.100';

$port = 9000;

$max_clients = 10;

// Array that will hold client information

$clients = Array();

// Create a TCP Stream socket

$sock = socket_create(AF_INET, SOCK_STREAM, 0);

// Bind the socket to an address/port

socket_bind($sock, $address, $port) or die('Could not bind to address');

// Start listening for connections

socket_listen($sock);

// Loop continuously

while (true) {

    
// Setup clients listen socket for reading

    
$read[0] = $sock;

    for (
$i = 0; $i < $max_clients; $i++)

    {

        if (
$client[$i]['sock']  != null)

            
$read[$i + 1] = $client[$i]['sock'] ;

    }

    
// Set up a blocking call to socket_select()

    
$ready = socket_select($read,null,null,null);

    
/* if a new connection is being made add it to the client array */

    
if (in_array($sock, $read)) {

        for ($i = 0; $i < $max_clients; $i++)

        {

            if (
$client[$i]['sock'] == null) {

                $client[$i]['sock'] = socket_accept($sock);

                break;

            }

            elseif (
$i == $max_clients - 1)

                print ("too many clients")

        }

        if (--
$ready <= 0)

            continue;

    }
// end if in_array

    

    // If a client is trying to write - handle it now

    
for ($i = 0; $i < $max_clients; $i++) // for each client

    {

        if (
in_array($client[$i]['sock'] , $read))

        {

            
$input = socket_read($client[$i]['sock'] , 1024);

            if ($input == null) {

                
// Zero length string meaning disconnected

                
unset($client[$i]);

            }

            
$n = trim($input);

            if ($input == 'exit') {

                
// requested disconnect

                
socket_close($client[$i]['sock']);

            } elseif (
$input) {

                // strip white spaces and write back to user

                
$output = ereg_replace("[ \t\n\r]","",$input).chr(0);

                
socket_write($client[$i]['sock'],$output);

            }

        } else {

            
// Close the socket

            
socket_close($client[$i]['sock']);

            unset(
$client[$i]);

        }

    }

}
// end while

// Close the master sockets

socket_close($sock);

?>



The basic functionality is the same as the first
example, with an added feature – when a user passes the string ‘exit’ the
program will terminate the connection with the user.


This program is very similar to the first, except that inside
the loop, we have four basic blocks of code.




  1. Set up the sockets for reading.
  2. Listen to new clients and set them up in the $client array.
  3. Listen to client writes and record the input.
  4. Handle the client input.

A new function in use is socket_select($read,null,null,null);
This runs the select() system call on
the given array of sockets and waits for them to change status. This will block
all the sockets until there is a change in status, which is then handled.




As a last point, you may find a situation where you would like
to broadcast information to the other clients connected (say in a many-to-many
chat environment). This can be achieved with the following code:



$output = 'This is my broadcast message'.chr(0);

for (
$j = 0; $j < MAX_CLIENTS; $j++) // for each client

{

    if (
$client[$j]['sock']) {

        
socket_write($client[$j]['sock'], $output);

    }

}





Practical Uses


Now that you know the basics of creating a socket server, the
only limitation is your imagination. Here are some ideas:


  • Chat server (using a text based or graphical interface). This can be for fun or real application
    (e.g. customer support representatives).
  • Real time information streaming (news, stocks etc.)
  • Streaming multimedia (images, videos and sounds)
  • Authentication server
  • Simple web, POP3, SMTP and FTP servers.


Furthermore, the sockets library can be used to
create client programs as well as servers.





Security


Security must be taken into consideration when creating
programs that will be accessible online. This is true for normal PHP scripts as
well as continuously running programs (such as socket servers).



There are many facets to a comprehensive security policy, from
programming, to access control and more.



There are many items to consider when planning your security
policy. Here are a few to get you started:

  • File access – you must limit file access.
    If the server allows access to files (e.g. web server), make sure you allow only
    files in a certain folder to be served out. It would be a bad mistake to serve
    /etc/passwd or /etc/shadow.

    File access can be limited by
    defining a parent or root folder and only allowing subfolders to be accessed by
    the socket server. Another good idea is to sanitize the data sent by the user to
    remove extraneous or dangerous characters (such as “../” used to access files in
    folders one level back).

  • Fail Safe – in cases where the server fails, you should make arrangements for it to fail safely.
    That is, if your socket server can no longer function as desired, it should be brought to a state
    where is can cause no damage – exit the program and halt execution.
  • Authentication – for sensitive services, it is recommended that you use authentication as part
    of the communications specifications. Even if you create a custom front-end in flash or Visual Basic,
    there is no guarantee that someone will not be able to “sniff” the network connection and decipher
    the protocol you are using (and any data transferred).



    One great way to do authentication is not to allow any actions to occur until a user has successfully
    authenticated himself (in the example above, this can be done by setting
    $client[$i]['authenticated'] = true upon successful authentication).
  • Encryption – encryption is a great way to protect sensitive information en-route to
    the server. Encrypted systems can be especially useful when combined with the
    above-suggested procedures (especially authentication over encrypted channels).
    Luckily, PHP has an excellent encryption library that you can use (the Mcrypt
    library – see
    http://www.php.net/mcrypt for further details).


One at a time please


Usually you will want the socket server to have one instance
operating at any one given time. In the above example, you use
socket_bind() or die('Could not bind to address').
This means that if the program tries to bind to a port
already in use, the program will exit giving an error message.



More refined program control can be achieved by using the
command line program pidof (/sbin/pidof). This command lists the process ID
(pid) of running programs. If you use pidof, make sure you supply the -x
argument to display the process id of shell scripts that are running as well.





Possible Additions and Improvements



  • Add process control and threads (can be done using PCNTL).
  • Add process control functions (discussed above) – to ensure that only a single
    instance is running at any one time (using /sbin/pidof –x program name).
  • Run a periodic script to check that the service is running. This can be done as a cron
    job in *nix (type man crontab in the *nix shell
    for further information) or as a Windows scheduled tasks (under Control Panel).
  • Front-end interface can be done in C++, VB, Flash (using XMLSockets), Java or any software that
    supports TCP/IP or UDP sockets.
  • If the server will be running unattended, you may wish to create a custom error handling function
    that will log to a text file or a database instead of printing the error messages to stdout.


About the Author


Ori Staub is a senior systems analyst, developer, and
consultant specializing in web-based solutions. He has developed many e-commerce
and web solutions to work tightly with existing client business
models.



Ori can be contacted directly at
os@zucker-staub.com



About Cal Evans

Many moons ago, at the tender age of 14, Cal touched his first computer. (We're using the term "computer" loosely here, it was a TRS-80 Model 1) Since then his life has never been the same. He graduated from TRS-80s to Commodores and eventually to IBM PC's. For the past 10 years Cal has worked with PHP and MySQL on Linux OSX, and when necessary, Windows. He has built on a variety of projects ranging in size from simple web pages to multi-million dollar web applications. When not banging his head on his monitor, attempting a blood sacrifice to get a particular piece of code working, he enjoys building and managing development teams using his widely imitated but never patented management style of "management by wandering around". Cal is currently based in Nashville, TN and is gainfully unemployed as the Chief Marketing Officer of Blue Parabola, LLC. Cal is happily married to wife 1.28, the lovely and talented Kathy. Together they have 2 kids who were both bright enough not to pursue a career in IT. Cal blogs at http://blog.calevans.com and is the founder and host of Day Camp 4 Developers

View all posts by Cal Evans

19 Responses to “Writing Socket Servers in PHP”

  1. rahulnagpal1989 Says:

    i want client side code to send message and show message back to client for making chat application.

  2. mkrve Says:

    I used your example to create a socket server.
    Its running great, but….

    Sometimes socket connections do not get closed correct by the other party, and these connections stay open…

    What would be a good way to build in a connection time-out.
    For example i would like to time-out a socket connection after about 10 minutes of inactivity.

  3. finish3r Says:

    Fatal error: Call to undefined function socket_create().

  4. finish3r Says:

    Do we not need to use ajax in this tutorial?. By not reloading the page.

  5. buccinator Says:

    or one could write a plugin from the examples provided with the sonic server daemon :p

    http://dev.pedemont.com/sonic

  6. revorf Says:

    Hi,
    I read article, and I can run this php script locally. But when I use another server, I am getting error:

    #!/usr/local/bin/php -q
    Warning: socket_accept() [function.socket-accept]: unable to accept incoming connection [4]: Interrupted system call in /home/users/kazek/public_html/index2.php on line 28
    socket_accept() failed: reason: Success

    Do you know any free server, which is able to run this script? I will be thankfull.

    regards

  7. j81godoy Says:

    What if I client disconnect without send the "exit command", the client could just stop sending. How can we unset the client in this case? It could cause to many connections all the time.

  8. greg1996 Says:

    Hi

    I’m trying to connect with flash, if I try to connect while the flash is in the editor (Adobe flash cs4) it connects. But if I upload the flash the php saves this to my log file:
    Tuesday 27th of October 2009 05:57:34 AM | New client connected: *My ip*
    Tuesday 27th of October 2009 05:57:34 AM | Client disconnected!
    notice the time difference/\
    is this normal?
    what should I do to fix it?

  9. shaileshfefar Says:

    hi friend if you know how to execute this socket programming php script then tell me it step by step in details plz……………..

  10. ellisgl Says:

    Here’s the code I whipped up with all the previous comments:
    <?php
    error_reporting(1);
    ini_set(‘display_errors’, ’1′);

    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    $max_clients = 10;

    socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
    socket_bind($socket, 0, 10000);
    socket_listen($socket, $max_clients);

    $clients = array(’0′ => array(‘socket’ => $socket));

    while(TRUE)
    {
    $read[0] = $socket;

    for($i=1; $i<count($clients)+1; ++$i)
    {
    if($clients[$i] != NULL)
    {
    $read[$i+1] = $clients[$i]['socket'];
    }
    }

    $ready = socket_select($read, $write = NULL, $except = NULL, $tv_sec = NULL);

    if(in_array($socket, $read))
    {
    for($i=1; $i < $max_clients+1; ++$i)
    {
    if(!isset($clients[$i]))
    {
    $clients[$i]['socket'] = socket_accept($socket);

    socket_getpeername($clients[$i]['socket'],$ip);

    $clients[$i]['ipaddy'] = $ip;

    socket_write($clients[$i]['socket'], ‘Welcome to my Custom Socket Server’."\r\n");
    socket_write($clients[$i]['socket'], ‘There are ‘.(count($clients) – 1).’ client(s) connected to this server.’."\r\n");

    echo ‘New client connected: ‘ . $clients[$i]['ipaddy'] .’ ‘;
    break;
    }
    elseif($i == $max_clients – 1)
    {
    echo ‘To many Clients connected!’."\r\n";
    }

    if($ready < 1)
    {
    continue;
    }
    }
    }

    for($i=1; $i<$max_clients+1; ++$i)
    {
    if(in_array($clients[$i]['socket'], $read))
    {
    $data = @socket_read($clients[$i]['socket'], 1024, PHP_NORMAL_READ);

    if($data === FALSE)
    {
    unset($clients[$i]);
    echo ‘Client disconnected!’,"\r\n";
    continue;
    }

    $data = trim($data);

    if(!empty($data))
    {
    if($data == ‘exit’)
    {
    socket_write($clients[$i]['socket'], ‘Thanks for trying my Custom Socket Server, goodbye.’."\n");
    echo ‘Client ‘,$i,’ is exiting.’,"\n";
    unset($clients[$i]);
    continue;
    }

    for($j=1; $j<$max_clients+1; ++$j)
    {
    if(isset($clients[$j]['socket']))
    {
    if(($clients[$j]['socket'] != $clients[$i]['socket']) && ($clients[$j]['socket'] != $socket))
    {
    echo($clients[$i]['ipaddy'] . ‘ is sending a message!’."\r\n");
    socket_write($clients[$j]['socket'], ‘[' . $clients[$i]['ipaddy'] . ‘] says: ‘ . $data . "\r\n");
    }
    }
    }
    break;
    }
    }
    }
    }
    ?>

    I have noticed that if I connect with first client – I get the server message. If I connect with a second client, I don’t get the server message until I send a message from the first. If I try to send more than one message from one client, it doesn’t show all the messages after one until I send a message from the 2nd client. It takes a couple messages back and fourth message before things "sync" up.

    I have yet to pin point the issue.. I am running under windows.

  11. garyebickford Says:

    I was able to add the ‘exit’ functionality to CaseyCollier’s nice PHP5-corrected version, by adding an elseif after the trim() as follows, :

    $data = trim($data);
    if ($data == ‘exit’) {
    socket_write($clients[$i]['socket'],"Thanks for trying my Custom Socket Server, goodbye.\n");
    echo "Client $i is exiting.\n";
    unset ($clients[$i]);
    continue;
    }

  12. _____anonymous_____ Says:

    This is a great article. However, after implementing the fixes mentioned in comments, the exit command is still not accepted, it is just processed as normal text…

  13. caseycollier Says:

    I took a swing at remaking the advanced portion of this script — sorry no comments or anything. But it will run fine with no errors maybe it will help someone out:

    #!/usr/bin/php5 -q
    <?php
    $socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
    $max_clients = 10;

    socket_set_option($socket,SOL_SOCKET,SO_REUSEADDR,1);
    socket_bind($socket,0,10000);
    socket_listen($socket,$max_clients);

    $clients = array(’0′ => array(‘socket’ => $socket));

    while(TRUE) {
    $read[0] = $socket;
    for($i=1;$i<count($clients)+1;$i++) {
    if($clients[$i] != NULL) {
    $read[$i+1] = $clients[$i]['socket'];
    }
    }

    $ready = socket_select($read,$write=NULL,$except=NULL,0);

    if(in_array($socket,$read)) {
    for($i=1;$i<$max_clients+1;$i++) {
    if(!isset($clients[$i])) {
    $clients[$i]['socket'] = socket_accept($socket);
    socket_getpeername($clients[$i]['socket'],$ip);
    $clients[$i]['ipaddy'] = $ip;

    socket_write($clients[$i]['socket'],"Welcome to my Custom Socket Server
    ");
    socket_write($clients[$i]['socket'],"There are " . (count($clients) – 1) . " client(s) connected to this server.
    ");

    echo("New client connected: " . $clients[$i]['ipaddy'] . "
    ");
    break;
    }
    elseif($i == $max_clients – 1) {
    echo("To many Clients connected!
    ");
    }
    if($ready < 1) {
    continue;
    }
    }
    }
    for($i=1;$i<$max_clients+1;$i++) {
    if(in_array($clients[$i]['socket'],$read)) {

    $data = @socket_read($clients[$i]['socket'],1024000, PHP_NORMAL_READ);

    if ($data === FALSE) {
    unset($clients[$i]);
    echo "Client disconnected!
    ";
    continue;
    }

    $data = trim($data);

    if(!empty($data)) {
    for($j=1;$j<$max_clients+1;$j++) {
    if(isset($clients[$j]['socket'])) {
    if(($clients[$j]['socket'] != $clients[$i]['socket']) && ($clients[$j]['socket'] != $socket)) {
    echo($clients[$i]['ipaddy'] . " is sending a message!
    ");
    socket_write($clients[$j]['socket'],"[" . $clients[$i]['ipaddy'] . "] says: " . $data . "
    ");
    }
    }
    }
    break;
    }
    }
    }
    }
    ?>

  14. caseycollier Says:

    I took a swing at remaking the advanced portion of this script — sorry no comments or anything. But it will run fine with no errors maybe it will help someone out:

    #!/usr/bin/php5 -q
    <?php
    $socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
    $max_clients = 10;

    socket_set_option($socket,SOL_SOCKET,SO_REUSEADDR,1);
    socket_bind($socket,0,10000);
    socket_listen($socket,$max_clients);

    $clients = array(’0′ => array(‘socket’ => $socket));

    while(TRUE) {
    $read[0] = $socket;
    for($i=1;$i<count($clients)+1;$i++) {
    if($clients[$i] != NULL) {
    $read[$i+1] = $clients[$i]['socket'];
    }
    }

    $ready = socket_select($read,$write=NULL,$except=NULL,0);

    if(in_array($socket,$read)) {
    for($i=1;$i<$max_clients+1;$i++) {
    if(!isset($clients[$i])) {
    $clients[$i]['socket'] = socket_accept($socket);
    socket_getpeername($clients[$i]['socket'],$ip);
    $clients[$i]['ipaddy'] = $ip;

    socket_write($clients[$i]['socket'],"Welcome to my Custom Socket Server
    ");
    socket_write($clients[$i]['socket'],"There are " . (count($clients) – 1) . " client(s) connected to this server.
    ");

    echo("New client connected: " . $clients[$i]['ipaddy'] . "
    ");
    break;
    }
    elseif($i == $max_clients – 1) {
    echo("To many Clients connected!
    ");
    }
    if($ready < 1) {
    continue;
    }
    }
    }
    for($i=1;$i<$max_clients+1;$i++) {
    if(in_array($clients[$i]['socket'],$read)) {

    $data = @socket_read($clients[$i]['socket'],1024000, PHP_NORMAL_READ);

    if ($data === FALSE) {
    unset($clients[$i]);
    echo "Client disconnected!
    ";
    continue;
    }

    $data = trim($data);

    if(!empty($data)) {
    for($j=1;$j<$max_clients+1;$j++) {
    if(isset($clients[$j]['socket'])) {
    if(($clients[$j]['socket'] != $clients[$i]['socket']) && ($clients[$j]['socket'] != $socket)) {
    echo($clients[$i]['ipaddy'] . " is sending a message!
    ");
    socket_write($clients[$j]['socket'],"[" . $clients[$i]['ipaddy'] . "] says: " . $data . "
    ");
    }
    }
    }
    break;
    }
    }
    }
    }
    ?>

  15. mogyiman Says:

    I made some progress with this nice example. Here are the corrections to get a fully working server:

    1, clients just meant to be plural and array with a small ‘a’
    //Array that will hold the client information
    $client = array();

    2, Socket close actions are interpreted even if the socket resource does not exist.
    //Close the socket
    if ($client[$i]['sock'] != null){
    socket_close($client[$i]['sock']);
    unset($client[$i]);
    }

  16. potsed Says:

    Hey, thanks for a great article.

    Just a couple of error i found while running the script.

    1. All client connections are closed when sending ‘exit’ from one of them.

    Explanation: I had two telnet sessions connected to the server, and when i typed exit in one of them, both closed.

    Fix: Just found the bug, will post fix when i can.

    2. Exit did not work without changing line 38 from "if ($input == ‘exit’)" to "if ($n == ‘exit’)"

    3. When exiting from a client the following warning is outputted on the server:
    "Warning: socket_select(): 6 is not a valid Socket resource in /path/to/server.php on line 31"

    This is just a first run of the script, so i have not had a chance to look at debugging it, but will write back some fixes asap.

  17. ace5 Says:

    Your tutorial is great! But I just don’t see what’s the use of the array $read.. It always gets filled with either the master socket or the cient communication socket, and it does never gets used. Also the two in_arrays seem a bit useless to me; isn’t it the same as doing if (1=1) ??

    Any comments on this appreciated!

  18. _____anonymous_____ Says:

    That is caused by a limitation in Zend’s engine, instead use a variable which is set to null. The following line works:
    $ready = socket_select($read, $write = NULL, $except = NULL, $tv_sec = NULL);

    There is also a missed semi colon on line 40, that line should be:
    print ("too many clients");

  19. jaranza1 Says:

    i got this error when i tried to copy,paste and run the code …

    Fatal error: variables can be passed by reference in C:\path\this_script.php on line 30 …