PHP Socket Server? What the pcntl_fork are streams!


By

Christopher Langton


@chrisdlangton


Source Code

Github


composer.json
{
  "require": {
    "php": "^7.0",
    "sockets/php-stream-socket-server": "^1.4"
  }
}
and run  composer install

pcntl_fork

When called from a running process pcntl_fork will open a new process on the operating system which will continue to execute in parallel.


Consider:

$pid = pcntl_fork();
if ( $pid == 0 ) {
/* This is the child process. Do something here. */
}

Ticks

Chewy aside, a tick is a special event that occurs internally in PHP each time it has executed a certain number of statements

Title

Tick syntax

Have you seen the declare function used like this before?

declare(ticks=1) echo 'I haz ticks yo!';

This produces only 1 output, because a tick occurs 1 time per statement, and zend counts ; and {} blocks as a statement.

declare(ticks=1) {{ echo 'tick'; }}
How many ticks printed?

How many printed here?
function tickFunc() { echo 'tick'; }
register_tick_function("tickFunc");
declare(ticks=2);

Ticks cont..

Why do we care about ticks?

  • They loosely correspond to the statements in your script

    When we fork this can cause unexpected execution blocks internally

  • You can register functions to execute when a tick occurs

    Great for profiling and debugging, as well as checking resources like mysql are alive

  • You can control how many statements it takes to set off a tick

    We want this set to 1 statement per tick

You'll encounter some pretty crazy unjustifiable scenarios when forking and leaving zend-ng to figure out statement blocks

Streams

Streams are;

  • Reliable, ordered, interprocess data transfer

  • TCP/IP and open files on the same system are most common

  • UDP streams are also possible

  • Communication between processes is possible using a socket pair

  • WebSockets are implemented using HTTP1.1 streams then  UPGRADE via RFC2817

Stream Syntax

Basic example
const SOCKET_WAIT = 
            0;
// open a tcp socket on specified open port
$socket = stream_socket_server('tcp://domain:port', $errNo, $errStr);
// zero blocks this process, waits indefinately until a client connects

// errors return as false and complete the while loop
    while ($connection = stream_socket_accept($socket, SOCKET_WAIT)) {
  // consume 1MB from the stream
    $message = stream_socket_recvfrom($connection, 1024);
  // peek this to not consume the data
  // use the message data, echo it back to the client
    fputs($connection, $message);
}
// Don't forget to disconnect sockets
    fclose($socket);
        

Putting it together

  • Process forking
    resource management
  • Session leader processes
    Zombies!
  • Ticks
    Consistency
  • Streams
    Reliable communication


Questions?


Github

References

PHP Socket Server? What the pcntl_fork are streams!

By Chris Langton

PHP Socket Server? What the pcntl_fork are streams!

Understanding streams in PHP7, the edge cases when forking processes that hold file descriptors that manage bi-directional messaging.

  • 1,760