Hello!
I'm writing a socket-handling class in PHP, and just got ready with the socketRead() function.
The function is designed to make scripts able to read from sockets without halting. It therefore forks(), and makes the fork loop for data with socket_read(). When a new line of data arrives, it writes the data to a file, and sends a SIGUSR to the parent. The parent reads the file, and calls a callbackfunktion.
Since I don't know how stable/good/fast/effective this is, I would be happy for som feedback. Pasting the class below, hoping someone takes time to read it 😉
class NetworkHandler
{
/**
* Constructor for NetworkHandler, set's some class vars
* @access public
* @return void
* @desc Constructor for NetworkHandler, set's some class vars
*/
function NetworkHandler ()
{
}
/**
* Function to read from a socket
*
* This function forks the script, and makes the fork loop for incoming data.
* When data arrives, it calls the callback funktion, that will have to take two parameters:
* One for the data (comes line by line) and one for the IP:Port that send it.
* If the connection get's broken, the second callbackfunction (third parameter) will be called.
* This function just have to take one argument, the remote IP:port.
*
* @param resource &$socket The socket to read from
* @param string $callback The function to call when data arrives.
* @param string $exit_callback The function to call when connection ends
* @access public
* @return bool
* @desc Function to read from a socket
*/
function socketRead (&$socket, $callback, $exit_callback)
{
// Create and check bufferfile
if (!($tmp = fopen(".bfr","w")))
return(FALSE);
fclose($tmp);
if (!(is_writable(".bfr")))
return(FALSE);
// Fork
if (($fork = pcntl_fork()) < 0)
return(FALSE);
if ($fork == 0)
{
// I'm the child
// Start looping for data
while (@$data = socket_read($socket, 1024, PHP_NORMAL_READ))
{
// Who send the data?
$sAddr = "";
$iPort = "";
socket_getpeername($socket, $sAddr, $iPort);
// Open bufferfile
$fil = fopen(".bfr","r+");
// Write data
fwrite($fil,$sAddr.":".$iPort."\n".$callback."\n".$data);
// Close bufferfile
fclose($fil);
// Send SIGUSR1 to parent
posix_kill(posix_getppid(), SIGUSR1);
}
// Connection ended
// Who?
$sAddr = "";
$iPort = "";
socket_getpeername($socket, $sAddr, $iPort);
// Open file
$fil = fopen(".bfr","r+");
// Write file
fwrite($fil, $sAddr.":".$iPort."\n".$exit_callback);
// Close file
fclose($fil);
// Send SIGUSR2 and die
posix_kill(posix_getppid(), SIGUSR2);
die();
}
// I'm the parent
// Declare signalhandlers
pcntl_signal(SIGUSR1, array($this, "signalHandler"));
pcntl_signal(SIGUSR2, array($this, "signalHandler"));
// Everything worked, return TRUE
return(TRUE);
}
/**
* Signal handler for SIGUSRs
* @param int $signal Signal
* @access private
* @return viod
* @see socketRead()
* @desc Signal handler for SIGUSRs
*/
function signalHandler($signal)
{
switch ($signal)
{
case SIGUSR1:
// New data have arrived
// Read file
$fil = file(".bfr");
// Strip shit
for ($n = 0; $n < sizeof($fil);$n++)
{
$fil[$n] = trim($fil[$n]);
}
// Callback
call_user_func($fil[1],$fil[2],$fil[0]);
break;
case SIGUSR2:
// Connection ended
// Read file
$fil = file(".bfr");
// Callback
call_user_func(trim($fil[1]), trim($fil[0]));
break;
}
}
}