Problem scenario:
Suppose you have a ecommerce site where customer can put an order. Then site will be notify you via sms or any device when new order found
Efficient Solved scenario:
You have to build a socket sever which check the new order and response you, then you will collect the new order from your e-commerce site
Prerequisites
- 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 example uses Linux, I will show everything using *nix environments
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.
Socket Servers normally run continuously as a service or a system daemon.
Types of Sockets
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 example , TCP sockets will be used to ensure that all the data is received intact.
Creating a Socket Server using PHP
/*********function to check new order******************/
function get_new_order()
{
$con=mysql_connect(HOST, USERNAME, PASSWORD);
mysql_select_db(DATABASE, $con);
$sql="select OrderId from customer_order where order_Status='0' "; //0 for new order
$query=mysql_query($sql,$con);
if(mysql_num_rows( $query)>0)
{
return true;
}
else return false;
}
/*************************************/
/********Socket Server*********************/
set_time_limit (0);
// Set the ip and port we will listen on
$address = '127.0.0.1';
$port = 6789;
// Create a TCP Stream socket
$sock = socket_create(AF_INET, SOCK_STREAM, 0); // 0 for SQL_TCP
// Bind the socket to an address/port
socket_bind($sock, 0, $port) or die('Could not bind to address'); //0 for localhost
// Start listening for connections
socket_listen($sock);
//loop and listen
while (true) {
/* Accept incoming requests and handle them as child processes */
$client = socket_accept($sock);
// Read the input from the client – 1024000 bytes
$input = socket_read($client, 1024000);
// Strip all white spaces from input
$output = ereg_replace("[ \t\n\r]","",$input)."\0";
$message=explode('=',$output);
if(count($message)==2)
{
if(get_new_order()) $response='NEW:1';
else $response='NEW:0';
}
else $response='NEW:0';
// Display output back to client
socket_write($client, $response);
socket_close($client);
}
// Close the master sockets
socket_close($sock);
Run the socketserver into your server
You can run this sever in several ways
1.using cronjob/crontab
2.using php CLI
3. as a daemon service
I will show you in *nix Enviroments
In Centos you can use like this
Chomd a+x SocketServer.php //to make executable
Php –q SocketServer.php //run using php_cli
You can also run as a system_daemon
nohup php SocketServer.php & //you must use & to create a pid, after using this command you can see the pid number
/** to kill the process**/
Kill pid_number
/*********************/
In Ubuntu you can use like this
pear install -f System_Daemon // to install pear package for system_daemon
now create a file named SockctCli.php like this
#!/usr/bin/php -q
/**
* System_Daemon turns PHP-CLI scripts into daemons.
*
* PHP version 5
*
* @category System
* @package System_Daemon
* @author Abdullah <ab.duetcse@yahoo.com>
* @copyright 2010 Abdullah
* @license GPL
* @link funphp.com/daemon_example
*/
/**
* System_Daemon Example Code
*
* If you run this code successfully, a daemon will be spawned
* but unless have already generated the init.d script, you have
* no real way of killing it yet.
*
* In this case wait 3 runs, which is the maximum for this example.
*
*
* In panic situations, you can always kill you daemon by typing
*
* killall -9 SocketCli.php
* OR:
* killall -9 php
*
Allowed arguments & their defaults */
$runmode = array(
'no-daemon' => true,
'help' => false,
'write-initd' => false,
);
/* Scan command line attributes for allowed arguments */
foreach ($argv as $k=>$arg) {
if (substr($arg, 0, 2) == '--' && isset($runmode[substr($arg, 2)])) {
$runmode[substr($arg, 2)] = true;
}
}
/* Help mode. Shows allowed argumentents and quit directly */
if ($runmode['help'] == true) {
echo 'Usage: '.$argv[0].' [runmode]' . "\n";
echo 'Available runmodes:' . "\n";
foreach ($runmode as $runmod=>$val) {
echo ' --'.$runmod . "\n";
}
die();
}
*/ Make it possible to test in source directory
This is for PEAR developers only */
ini_set('include_path', ini_get('include_path').':..');
/* Include Class */
error_reporting(E_ALL);
require_once 'System/Daemon.php';
/* Setup */
$options = array(
'appName' => 'SocketCli',
'appDir' => dirname(__FILE__),
'appDescription' => 'Run a socket server to listen printer request',
'authorName' => 'Md. Abdullah Bin salam',
'authorEmail' => 'ab.duetcse@gmail.com',
'sysMaxExecutionTime' => '0',
'sysMaxInputTime' => '0',
'sysMemoryLimit' => '1024M',
'appRunAsGID' => 1000,
'appRunAsUID' => 1000,
);
System_Daemon::setOptions($options);
/* This program can also be run in the forground with runmode --no-daemon */
if (!$runmode['no-daemon']) {
/* Spawn Daemon */
System_Daemon::start();
}
/* With the runmode --write-initd, this program can automatically write a
system startup file called: 'init.d'
This will make sure your daemon will be started on reboot */
if (!$runmode['write-initd']) {
System_Daemon::info('not writing an init.d script this time');
} else {
if (($initd_location = System_Daemon::writeAutoRun()) === false) {
System_Daemon::notice('unable to write init.d script');
} else {
System_Daemon::info(
'sucessfully written startup script: %s',
$initd_location
);
}
}
require_once '/var/www/SocketServer/SocketServer.php';
/* Run your code
Here comes your own actual code
This variable gives your own code the ability to breakdown the daemon: */
$runningOkay = true;
/* This variable keeps track of how many 'runs' or 'loops' your daemon has
done so far. For example purposes, we're quitting on 3. */
$cnt = 1;
/* While checks on 3 things in this case:
- That the Daemon Class hasn't reported it's dying
- That your own code has been running Okay
- That we're not executing more than 3 runs */
while (!System_Daemon::isDying() && $runningOkay ) {
/* What mode are we in? */
$mode = '"'.(System_Daemon::isInBackground() ? '' : 'non-' ).
'daemon" mode';
/* Log something using the Daemon class's logging facility
Depending on runmode it will either end up:
- In the /var/log/logparser.log
- On screen (in case we're not a daemon yet) */
System_Daemon::info('{appName} running in %s %s/3',
$mode,
$cnt
);
/* In the actuall logparser program, You could replace 'true'
With e.g. a parseLog('vsftpd') function, and have it return
either true on success, or false on failure. */
$runningOkay = true;
/*$runningOkay = parseLog('vsftpd');
Should your parseLog('vsftpd') return false, then
the daemon is automatically shut down.
An extra log entry would be nice, we're using level 3,
which is critical.
Level 4 would be fatal and shuts down the daemon immediately,
which in this case is handled by the while condition. */
if (!$runningOkay) {
System_Daemon::err('parseLog() produced an error, '.
'so this will be my last run');
}
/* Relax the system by sleeping for a little bit
iterate also clears statcache */
System_Daemon::iterate(2);
$cnt++;
}
/* Shut down the daemon nicely
This is ignored if the class is actually running in the foreground*/
System_Daemon::stop();
Execute
Just make your daemon script executable, and then execute it:
chmod a+x ./SocketCli.php<
./ SocketCli.php
Check
Your daemon has no way of communicating through your console, so check for messages in:
tail /var/log/ SocketCli.log
And see if it's still running:
ps uf -C SocketCli.php
Kill
Without the start/stop files (see below for howto), you need to:
killall -9 SocketCli.php
Autch.. Let's work on those start / stop files, right?
Start / Stop files (Debian & Ubuntu only)
Real daemons have an init.d file. Remember you can restart Apache with the following statement?
/etc/init.d/apache2 restart
That's a lot better than killing. So you should be able to control your own daemon like this as well:
/etc/init.d/ SocketCli stop
/etc/init.d/ SocketCli start
Now your server is build and run into the server as a service like apache service.
Test your server
Open a terminal and telnet
telnet example.com 6789
//example.com –your server domain where running your socketserver
//6789—port number of the socket server
Check=1 //send a message to check new order
After that you will get response from server like
New:1 or New:0
You can do anything according to server response
Practical Uses
There are several uses of the socket server such as
- 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.
10 Responses to “Create a socket server in php and run as a service”
Carry on Abd, nice article…
Thanks
Terrific website! I thoroughly enjoyed your content material …very nicely written.
In think this article is gonna be very useful to me because, currently, I need to develop uninterrupted multithreaded background processes as part of our project. I need info on how to make it multithreaded. Anybody having a link that should kindly help me. kudos!
All I can say is maintain it up. This blog is so essential in a time when everybody just wants to talk about how several individuals someones cheated on their wife with. I mean, thanks for bringing intelligence back to the web, its been sorely missed. Great stuff. Please maintain it coming!
Very helpful article about socket programmimg
dear sir… what kind of server i need and type of IP (static/dynamic) ??
Hi Abdullah – do you have any experience running it as a windows service?
Yes, I have eperienced with windows service.
You can use mongrel to create windows service
Thank you very much.