Tag Archives: PHP Socket

PHP Socket Client

This is a simple client that is running two different requests. One at every 2 seconds and another every 5 minutes. The 2 second one retrieved data from server and the 5 minute one sends data to server.

<?php
set_time_limit(0);
ob_implicit_flush();

$host    = "xxx.xxx.xxx.xxx";
$port    = 1250;

$lastUpdate = time();

while(1)
{
    if(time() - $lastUpdate > 300) //if 5 minutes elapsed
    {
        $message = "action=4512|temp=29.67|paM=10025.69|paH=125.69|led1=1|led2=0\r\n"; // the data to be sent separated by | The \r\n is important - it will tell the server that the string/data ends there
        // create socket
        $socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
        // connect to server
        $result = socket_connect($socket, $host, $port) or die("Could not connect to server\n");  
        
        // send command/query to server
        socket_write($socket, $message, strlen($message)) or die("Could not send data to server\n");
        // get server response
        $result = socket_read ($socket, 1024, PHP_NORMAL_READ) or die("Could not read server response\n"); // 1024 is the max bytes that the socket will read if no \r\n is encountered. For the \n\r terminator PHP_NORMAL_READ is needed.
        echo "Reply From Server: ".$result."\n";
        
        // close socket
        socket_close($socket);
        
        $lastUpdate = time();
    }
    else
    {
        $message = "action=1223\r\n";
        // create socket
        $socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
        // connect to server
        $result = socket_connect($socket, $host, $port) or die("Could not connect to server\n");  
        
        // send command/query to server
        socket_write($socket, $message, strlen($message)) or die("Could not send data to server\n");
        // get server response
        $result = socket_read ($socket, 1024, PHP_NORMAL_READ) or die("Could not read server response\n");
        echo "Reply From Server: ".$result."\n";
        
            // close socket
        socket_close($socket);
    }
    
    flush(); //may be this can be removed
    sleep(2);
    flush();
}
?>

 

PHP Socket Server – Running as Daemon and Multiple Connections

Code Courtesy: lars at opdenkamp dot eu

A socket server written in PHP. This can accept multiple connections and runs as a daemon.

pcntl_fork() is thing here that is making this all possible.

<?php
/**
  * Listens for requests and forks on each connection
  */

$__server_listening = true;

//error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();
declare(ticks = 1);

become_daemon();

/* nobody/nogroup, change to your host's uid/gid of the non-priv user */
change_identity(1000, 1000);

/* handle signals */
pcntl_signal(SIGTERM, 'sig_handler');
pcntl_signal(SIGINT, 'sig_handler');
pcntl_signal(SIGCHLD, 'sig_handler');

/* change this to your own host / port */
server_loop("192.168.0.1", 1250);

/**
  * Change the identity to a non-priv user
  */
function change_identity( $uid, $gid )
{
    if( !posix_setgid( $gid ) )
    {
        print "Unable to setgid to " . $gid . "!\n";
        exit;
    }

    if( !posix_setuid( $uid ) )
    {
        print "Unable to setuid to " . $uid . "!\n";
        exit;
    }
}

/**
  * Creates a server socket and listens for incoming client connections
  * @param string $address The address to listen on
  * @param int $port The port to listen on
  */
function server_loop($address, $port)
{
    GLOBAL $__server_listening;

    if(($sock = socket_create(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        echo "failed to create socket: ".socket_strerror($sock)."\n";
        exit();
    }

    if(($ret = socket_bind($sock, $address, $port)) < 0)
    {
        echo "failed to bind socket: ".socket_strerror($ret)."\n";
        exit();
    }

    if( ( $ret = socket_listen( $sock, 0 ) ) < 0 )
    {
        echo "failed to listen to socket: ".socket_strerror($ret)."\n";
        exit();
    }

    socket_set_nonblock($sock);
   
    echo "waiting for clients to connect\n";

    while ($__server_listening)
    {
        $connection = @socket_accept($sock);
        if ($connection === false)
        {
            usleep(100);
        }elseif ($connection > 0)
        {
            handle_client($sock, $connection);
        }else
        {
            echo "error: ".socket_strerror($connection);
            die;
        }
    }
}

/**
  * Signal handler
  */
function sig_handler($sig)
{
    switch($sig)
    {
        case SIGTERM:
        case SIGINT:
            exit();
        break;

        case SIGCHLD:
            pcntl_waitpid(-1, $status);
        break;
    }
}

/**
  * Handle a new client connection
  */
function handle_client($ssock, $csock)
{
    GLOBAL $__server_listening;

    $pid = pcntl_fork();

    if ($pid == -1)
    {
        /* fork failed */
        echo "fork failure!\n";
        die;
    }elseif ($pid == 0)
    {
        /* child process */
        $__server_listening = false;
        socket_close($ssock);
        interact($csock);
        socket_close($csock);
    }else
    {
        socket_close($csock);
    }
}

function interact($socket)
{
    $conn = mysql_connect("localhost","xxxxxxxx","xxxxxxxxxxx");
    if(!$conn)
    {
        echo "Error: failed to connect DB";
        die();
    }
    
    if(!mysql_select_db("xxxxxxxx",$conn))
    {
        echo "Error: failed to connect DB";
        die();
    }
    
    // read client input
    $input = socket_read($socket, 1024, PHP_NORMAL_READ);
    
    $buff = explode("|",$input);
    $len = count($buff);
    $temp = explode("=",$buff[0]);
    $temp[1] = intval($temp[1]);
    if($temp[0]!="action" && ($temp[1]!=1 || $temp[1]!=2 ))  //1=read 2=write -- these are just random numbers and has no other significance.
    {
        $output = "Error\r\n";
    } 

    
    if($temp[1] == 1)
    {
        $result = mysql_query("select * from led_status");
        $rows = mysql_fetch_array($result);
        $output = "led_1=".$rows['led_1']."|led_2=".$rows['led_2']."\r\n";
    }

    if($temp[1] == 2)
    {
        $queryW = "insert into weather set ";
        $queryL = "update led_status set ";

        for($i=1; $i<$len; $i++)
        {
            $temp = explode("=",$buff[$i]);
            switch($temp[0])
            {
                   case 'temp':
                    $queryW .= "temperature=" . floatval($temp[1]).", ";
                break;
                
                case 'paH':
                    $queryW .= "paH=" . floatval($temp[1]) .", ";    
                break;
                
                case 'paM':
                    $queryW .= "paM=" . floatval($temp[1]).", ";
                break;
                
                case 'led_1':
                    $queryL .= "led_1" . floatval($temp[1]) .", ";    
                break;
                
                case 'led_2':
                    $queryL .= "led_2=" . float_val($temp[1]).", ";        
            }
        }        
        
        $queryW .= " time=".time();
        $queryL .= " time=".time();
        
        mysql_query($queryL);
        mysql_query($queryW);
        
        $output = "Update Success\r\n";
    }
            
    /* TALK TO YOUR CLIENT */ 
    socket_write($socket,$output, strlen($output));    
    mysql_close();
}

/**
  * Become a daemon by forking and closing the parent
  */
function become_daemon()
{
    $pid = pcntl_fork();
   
    if ($pid == -1)
    {
        /* fork failed */
        echo "fork failure!\n";
        exit();
    }elseif ($pid)
    {
        /* close the parent */
        exit();
    }else
    {
        /* child becomes our daemon */
        posix_setsid();
        chdir('/');
        umask(0);
        return posix_getpid();

    }
}
?>