You want to do WHAT with PHP? Chapter 4

2 Comments

Communication is key to building applications now and for the future.  While it is not something that I think that everyone should do, I have not seem many applications that make good use of streams in PHP.  Streams can be immensely useful in the right situations, but a lot of developers are not really aware of how streams can be used.  In this excerpt from chapter 4 of my book "You want to do WHAT with PHP?" I talk about how you can use streams for fun, and maybe for profit.  While I don't think you will end up basing your application around streams it is a really good idea to know how streams work.  With that in mind, here is an excerpt from the book.

   Chapter 1: Networking and Sockets
   Chapter 2: Binary Protocols
   Chapter 3: Character Encoding
   Chapter 4: Streams
   Chapter 5: SPL
   Chapter 6: Asynchronous Operations with Some Encryption Thrown In
   Chapter 7: Structured File Access
   Chapter 8: Daemons
   Chapter 9: Debugging, Profiling, and Good Development
   Chapter 10: Preparing for Success

 

On some occasions it may be necessary to change stream properties on the fly. To demonstrate this, we will write a simple echo client/server application. The server will listen on a port, echoing whatever it receives and writing back to the socket whatever it had received. Let’s start with just the basics.

First the server

$sock = stream_socket_server(
    'tcp://0.0.0.0:10000',
    $errno,
    $errstr
);

if (!$sock) die($errstr);

while (($client = stream_socket_accept($sock)) !== false) {
    while (($line = fgets($client)) != null) {
        echo $line;
    }
}

Figure 4.12 Simple TCP based server

Then the client.

$sock = stream_socket_client(
    'tcp://localhost:10000',
    $errno,
    $errstr
);

if (!$sock) die($errstr);

$in = fopen('php://stdin', 'r');
while (($line = fgets($in)) != null) {
    fwrite($sock, $line, strlen($line));
}

Figure 4.13 Simple TCP based client

We can run both of these quite simply from the command line. When we do, we get the following output.

From the client

$ php ./enc.client.php
You want to do WHAT with PHP?

This is reading the data we type in to the console, sends it to the server and then writes out whatever it is that the server sends back. The server prints out much the same.

$ php enc.server.php
You want to do WHAT with PHP?

No surprise here. It’s doing exactly what you would expect. But let’s add a little code to our client.

$sock = stream_socket_client(
    'tcp://localhost:10000',
    $errno
,
    $errstr
);

if (!$sock) die($errstr);

$in = fopen('php://stdin', 'r');
$filter
= null;
while (($line = fgets($in)) != null) {
    if
(trim($line) === 'COMPRESS') {
        fwrite(
$sock, $line, strlen($line));
        $filter
= stream_filter_append(
            $sock
,
            'bzip2.compress',
            STREAM_FILTER_WRITE
        );

        echo "nCompression Enabled.n";
        continue
;
    }

    fwrite(
$sock, $line, strlen($line));
}

Figure 4.14 Code to enable compression on the stream

What this code is doing is reading the input from the input line, just as it was before, but appending the BZip2 filter when the word “COMPRESS” is typed. When we enable the filter we call stream_filter_append(), take the return value and store it in a sort of global variable. The return value is a resource that describes the socket and filter combination. Later on, when we want to remove the filter, we simply pass the $filter variable to stream_filter_remove() and that filter will flush its contents and be removed. The flushing part is the primary reason why we are using it here. Compression engines work in blocks and as such may not actually send data to the endpoint when you write to it. Removing the filter causes the stream to flush thereby sending all data to the client.

When we run client code we can type these commands, and any other text, simply on the keyboard.

$ php ./enc.client.php
You want to do WHAT with PHP?
COMPRESS
Compression Enabled.
You want to do WHAT with PHP?

Figure 4.15 Client output of enabled compression

Easy enough. But the server side looks quite different.

$ php ./enc.server.php
You want to do WHAT with PHP?
COMPRESS
BZh41AY&SYb@ @D $a 1M211HÉ gHñ%,­#aâ±3)ÂöÏÐ

Figure 4.16 Server output of enabled compression

We see “You want to do WHAT with PHP?” in clear text once, followed by a bunch of binary data. That is about what we would expect to see since after typing in “COMPRESS” we were instructing the client to start compressing the stream.

To make sure that both sides are happy, the next step is to add a read filter on the server side.

2 thoughts on “You want to do WHAT with PHP? Chapter 4

  1. Hi!
    Thanks for the article, it’s very interesting.
    But I had some problems with running your example code.
    enc.server.php should be run before enc.client.php or it results connection refusion error:
    PHP Warning: stream_socket_client(): unable to connect to tcp://localhost:11111 (Connection refused)
    And second, the server outputs nothing after enabled compression, what can be wrong there?
    I’m using Ubuntu Linux
    [email protected] ~ $ php -v
    PHP 5.3.3-1ubuntu9.1 with Suhosin-Patch (cli) (built: Oct 15 2010 14:17:04)
    Copyright (c) 1997-2009 The PHP Group
    Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
    with Xdebug v2.1.0, Copyright (c) 2002-2010, by Derick Rethans

Leave a Reply

Your email address will not be published. Required fields are marked *