CodeIgniter Forums
How to keep a php socket open - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Using CodeIgniter (https://forum.codeigniter.com/forumdisplay.php?fid=5)
+--- Forum: General Help (https://forum.codeigniter.com/forumdisplay.php?fid=24)
+--- Thread: How to keep a php socket open (/showthread.php?tid=68245)



How to keep a php socket open - MarkWS7M - 06-15-2017

Hi all,

I'm using CodeIgniter as a front end for a home control system.

One of the devices I want to control has a socket interface.  To talk to it I have to open the socket and keep it open while I perhaps send/receive multiple packets based on links on the control webpage.

I have never tried to do this in php in general and I seem to think that based on my prior experience this is not something I can do as the instance is pretty much created on each request if I am right.

I may not be explaining this well but here is the basic idea:

127.0.0.1/index.php/control

This would display a control web page with various links.  One of the links would be something like initiate communication with power device.  So this might be something like:

127.0.0.1/index.php/control/initiatepowercomm

In the initiatepowercomm method in the control controller I would need to open a socket in php.  I need this socket to remain open so I can't destroy the instance of the socket.  Later commands need that socket to be open.  The problem is the power device "wakes up" when the socket is opened and accepts commands.  It "goes to sleep" when the socket closes.  So I cannot be opening and closing the socket on each request.  For example after doing the line above to initiate comm I might want to do something like:

127.0.0.1/index.php/control/setuppowercommparms

This would need to use the prior opened socket and send a bunch of stuff to the power controller.  Basically I need something to hold the socket open until I at some point terminate the connection.

Am I correct that doing this directly in php with CodeIgniter is not going to work?  IE it seems that when say the controller code initiatepowercomm finishes that the php socket I opened will likely die since the instance of php dies.  Is that correct?

If I am correct then I guess my only other way to do this is a small daemon program that I can make calls to from php that can manage the socket and keep it open.

I am open to other ideas.

Thanks in advance!


RE: How to keep a php socket open - skunkbad - 06-15-2017

It's my understanding that you must use PHP CLI if you want to run scripts without time limits. You can certainly use CodeIgniter via CLI, and I've done so, but not used sockets successfully. If on a linux server, you can use PHP's exec function or shell_exec function to start a long running processes.

This is something that I was playing around with a few months ago:

PHP Code:
<?php
defined
('BASEPATH') OR exit('No direct script access allowed');
/**
 * This class allows us to easily run a bash script via PHP,
 * and monitor for when it is finished. We could obviously
 * come up with other creative ways to check if a process
 * has completed, but the class provides one that should 
 * always work.
 *
 * Make sure that the file is executable for the www-data user.
 */

class Background_process
{
    
/**
     * Run a command in bash via php's exec function.
     * The output of the command replaces the contents
     * of the background process log file. The PID is
     * added to the exec function's 2nd parameter, which
     * allows us to return it.
     *
     * @param  string  bash command to run
     * @return  int  the process ID
     */
    
public function run$cmd '' )
    {
        
$log APPPATH 'logs/background_process.log';

        
execsprintf("%s > %s 2>&1 & echo $!"$cmd$log ), $pid_array );

        return (int) 
$pid_array[0];
    }
    
    
// -----------------------------------------------------------------------

    /**
     * Check if background process still running.
     * PHP's shell_exec function is used because it
     * can return more than one line of output from
     * the ps command. We run ps with the PID of the 
     * process we want to check. If it's running, the 
     * output of ps will have more than one line.
     */
    
public function is_running$pid )
    {
        if( (int) 
$pid )
        {
            try{
                
$result shell_execsprintf("ps %d"$pid) );

                if( 
countpreg_split("/\n/"$result) ) > 2)
                    return 
'TRUE';
            }
            catch( 
Exception $e ){}
        }

        return 
'FALSE';
    }
    
    
// -----------------------------------------------------------------------

}

/* End of file Background_process.php */
/* Location: /libraries/Background_process.php */ 

Run in a controller:

PHP Code:
/**
 * Start a background process using the Background_process library.
 */
public function background_process()
{
    
$this->load->library('background_process');

    
$pid $this->background_process->runAPPPATH 'resources/Testing/background_process_test.sh' );

    echo 
anchor('test/monitor_background_process/' $pid'Check if it is running' );
}

// -----------------------------------------------------------------------

/**
 * Start a background process using the Background_process library
 */
public function monitor_background_process$pid )
{
    
$this->load->library('background_process');

    echo 
'Running: ' $this->background_process->is_running$pid );
}

// -----------------------------------------------------------------------