PHP sockets

Post Reply
User avatar
Rksk
Major
Major
Posts: 730
Joined: Thu Jan 07, 2010 4:19 pm
Location: Rathnapura, Sri Lanka

PHP sockets

Post by Rksk » Wed Oct 13, 2010 4:24 pm

I have heard that, PHP socket function is very usefull to communicate among servers.
I think it can also use to communicate PCs and servers.

But i could not find any usefull example from the NET, i tried by google.
I found some, but i can't understand these port,server address...

Please help me with an example witch explains everything.

Thanks. :D
User avatar
Rksk
Major
Major
Posts: 730
Joined: Thu Jan 07, 2010 4:19 pm
Location: Rathnapura, Sri Lanka

Re: PHP sockets

Post by Rksk » Wed Oct 13, 2010 6:25 pm

saman has posted an article on this topic here https://robot.lk/viewtopic.php?f=50&p=4412
Thank you saman.

can anyone post an example code to create a connection and communicate between a php server and a pc.

thanks.

[ Post made via Mobile Device ] Image
User avatar
Saman
Lieutenant Colonel
Lieutenant Colonel
Posts: 828
Joined: Fri Jul 31, 2009 10:32 pm
Location: Mount Lavinia

Re: PHP sockets

Post by Saman » Wed Oct 13, 2010 6:49 pm

Do you know the theory behind socket communication ? This is discussed under Inter Process Communication (IPC) in System Programming. I'll brief a bit on that since it is the right way to learn something perfectly.

Knowing it through php will restrict you only to use sockets under php. If you have to use Java or C++ to implement socket communication you will not be able to do that.

Computer Networks is a massive subject. But I'll try my best to brief it with my article What is socket communication which was shorten to give you a quick idea.

If you need to know more about this subject refer to book: Data and Computer Communications, William Stallings. This explains things in a very simple but descriptive way. Also, there are some video lectures under Computer Networks in Computer Science section.

Now, lets discuss php sockets.

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 8000, 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).

Code: Select all

#!/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.30'; 
$port = 8000; 

// 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

Code: Select all

#!/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.30'; 
$port = 8000; 
$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:

Code: Select all

$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:
  1. Chat server (using a text based or graphical interface). This can be for fun or real application (e.g. customer support representatives).
  2. Real time information streaming (news, stocks etc.)
  3. Streaming multimedia (images, videos and sounds)
  4. Authentication server
  5. 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.

Another two good tutorials are at http://www.devshed.com/c/a/PHP/Socket-P ... -With-PHP/ and http://www.codewalkers.com/c/a/Miscella ... ts-in-PHP/.
Post Reply

Return to “PHP & MySQL”