Socket Programming
Socket programming involves connecting to remote machines on LAN or over the internet using ip addresses and port number.
For example google.com has an ip "173.194.36.3" and runs http server on port 80. So a socket application can connect to that ip address on that particular port number and start data communication.
Socket extension
Php comes with a socket extension which provide c-style socket functions and can be used to write socket programs.
However the socket extension is not the only option to do socket programming in php.
Another technique is to use streams, like file streams. First lets take a look at how the socket extension code looks like.
if(!($sock = socket_create(AF_INET, SOCK_STREAM, 0))) { perror("Could not create socket"); } echo "Socket created n"; //Connect socket to remote server if(!socket_connect($sock , '74.125.235.20' , 80)) { perror("Could not connect"); } echo "Connection established n"; $message = "GET / HTTP/1.1rnrn"; //Send the message to the server if( ! socket_send ( $sock , $message , strlen($message) , 0)) { perror("Could not send data"); } echo "Message send successfully n"; //Now receive reply from server if(socket_recv ( $sock , $buf , 500 , MSG_WAITALL ) === FALSE) { perror("Could not receive data"); } echo $buf; ///Function to print socket error message function perror($msg) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die("$msg: [$errorcode] $errormsg n"); }
The above program connects to google.com ip address on port number 80 and then sends http request and receives the output.
The functions called are socket_create, socket_connect, socket_send and socket_recv.
The same program can be implemented in a bit different style using file streams.
1. Streams
Lets take a look.
$fp = fsockopen("www.google.com", 80, $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br />n"; } else { $out = "GET / HTTP/1.1rnrn"; ///Send data fwrite($fp, $out); ///Receive data - in small chunks :) while (!feof($fp)) { echo fgets($fp, 128); } fclose($fp); }
The fsockopen function creates the socket and the connection together. The fwrite function sends data and fread receives data. Simple and similar to reading/writing from file streams. The above example creates a tcp socket. To create udp socket the socket stream wrapper has to be specified like this
$fp = fsockopen("udp://127.0.0.1", 13, $errno, $errstr);
The stream wrapper for tcp is ofcourse tcp://
The general syntax for the socket url is
$protocol://$host:$port
The above style is quick and easy alternative to the socket extension. And it does not require any extra extension and works inside php. There is another function called stream_socket_client that can do the same thing as fsockopen
$fp = stream_socket_client("tcp://www.google.com:80", $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br />n"; }
The socket url structure is same. Only that the port number does not have an extra parameter.
That much is all about writing socket clients. Next thing to code is socket servers. Programs that accept incoming socket connections and respond to their requests.
2. Socket Server using Streams
$server = stream_socket_server("tcp://0.0.0.0:4444", $errno, $errorMessage); if ($server === false) { throw new UnexpectedValueException("Could not bind to socket: $errorMessage"); } for (;;) { $client = stream_socket_accept($server); if ($client) { echo 'Connection accepted from '.stream_socket_get_name($client, false) . "n"; stream_copy_to_stream($client, $client); fclose($client); } }
Run the above php script to start the socket server. Start another terminal and connect to this server.
$ telnet localhost 4444 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. sd sd
The server acts as a simple echo server, by sending back the same message it receives. This server has a limitation, that it cannot handle multiple connections. Once a client connects to it, then it just serves that particular client.
3. Handle multiple clients
<?php // open a server on port 4444 $server = stream_socket_server("tcp://0.0.0.0:4444", $errno, $errorMessage); if ($server === false) { die("Could not bind to socket: $errorMessage"); } $client_socks = array(); while(true) { //prepare readable sockets $read_socks = $client_socks; $read_socks[] = $server; //start reading and use a large timeout if(!stream_select ( $read_socks, $write, $except, 300000 )) { die('something went wrong while selecting'); } //new client if(in_array($server, $read_socks)) { $new_client = stream_socket_accept($server); if ($new_client) { //print remote client information, ip and port number echo 'Connection accepted from ' . stream_socket_get_name($new_client, true) . "n"; $client_socks[] = $new_client; echo "Now there are total ". count($client_socks) . " clients.n"; } //delete the server socket from the read sockets unset($read_socks[ array_search($server, $read_socks) ]); } //message from existing client foreach($read_socks as $sock) { $data = fread($sock, 128); if(!$data) { unset($client_socks[ array_search($sock, $client_socks) ]); @fclose($sock); echo "A client disconnected. Now there are total ". count($client_socks) . " clients.n"; continue; } //send the message back to client fwrite($sock, $data); } }
The stream_select function takes arrays of socket to check for reading, writing or errors.
stream_select ( $read_socks, $write, $except, 300000 )
Whenever a certain event occurs on any of the sockets, stream_select will return and each array will be filled with the sockets that had events.
For example if one of the read sockets received a message from client then select will fill the read_socks array with the socket and return.
Similarly incoming new connections will also cause stream_select to return. In this case we do not have anything in the write and except socket arrays.
$ php /var/www/socket.php Connection accepted from 127.0.0.1:42203 Now there are total 1 clients. Connection accepted from 127.0.0.1:42204 Now there are total 2 clients. Connection accepted from 127.0.0.1:42205 Now there are total 3 clients. A client disconnected. Now there are total 2 clients. A client disconnected. Now there are total 1 clients. A client disconnected. Now there are total 0 clients.
The above output of the server console shows how 3 clients connected and then disconnected away. That much being on sockets for now, check out the manual pages for more information.
Conclusion
For a tutorial on programming sockets in php check out this post:
PHP Socket programming Tutorial - How to code Client and Server
How can i select port of printer to send print to it on button click? any help please
how i can stream a video to the server with php sockets
how can i send a message to a selected user only? example: user id:2 send a messaje to user id:5 like a private message, the public room is there and a private room to two users, and multiple public rooms and private messages?? thank
Hey ! Nice article ,
I have used this , but I am stuck at 256 clients connections but thats the limit I cna not expand that,
I am stuck there , can you help ?
I am using windows server.
nice! I’m experimenting with proc_open, set_stream_blocking and stream_select with a python script that takes about a minute to process. trying to find a way to display output from the python script to the browser as it comes.