Skip to content

Commit 4eac9d3

Browse files
authored
Merge pull request #102 from clue-labs/usage
Improve usage documentation
2 parents 1823123 + c33d7f1 commit 4eac9d3

File tree

1 file changed

+87
-7
lines changed

1 file changed

+87
-7
lines changed

README.md

Lines changed: 87 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ descriptor based implementation with an in-memory write buffer.
1313

1414
**Table of contents**
1515

16-
* [API](#api)
16+
* [Stream usage](#stream-usage)
1717
* [ReadableStreamInterface](#readablestreaminterface)
1818
* [data event](#data-event)
1919
* [end event](#end-event)
@@ -34,6 +34,7 @@ descriptor based implementation with an in-memory write buffer.
3434
* [end()](#end)
3535
* [close()](#close-1)
3636
* [DuplexStreamInterface](#duplexstreaminterface)
37+
* [Creating streams](#creating-streams)
3738
* [ReadableResourceStream](#readableresourcestream)
3839
* [WritableResourceStream](#writableresourcestream)
3940
* [DuplexResourceStream](#duplexresourcestream)
@@ -42,8 +43,31 @@ descriptor based implementation with an in-memory write buffer.
4243
* [Install](#install)
4344
* [Tests](#tests)
4445
* [License](#license)
46+
* [More](#more)
4547

46-
## API
48+
## Stream usage
49+
50+
ReactPHP uses the concept of "streams" throughout its ecosystem to provide a
51+
consistent higher-level abstraction for processing streams of arbitrary data
52+
contents and size.
53+
While a stream itself is a quite low-level concept, it can be used as a powerful
54+
abstraction to build higher-level components and protocols on top.
55+
56+
If you're new to this concept, it helps to think of them as a water pipe:
57+
You can consume water from a source or you can produce water and forward (pipe)
58+
it to any destination (sink).
59+
60+
Similarly, streams can either be
61+
62+
* readable (such as `STDIN` terminal input) or
63+
* writable (such as `STDOUT` terminal output) or
64+
* duplex (both readable *and* writable, such as a TCP/IP connection)
65+
66+
Accordingly, this package defines the following three interfaces
67+
68+
* [`ReadableStreamInterface`](#readablestreaminterface)
69+
* [`WritableStreamInterface`](#writablestreaminterface)
70+
* [`DuplexStreamInterface`](#duplexstreaminterface)
4771

4872
### ReadableStreamInterface
4973

@@ -754,6 +778,38 @@ order to be considered a well-behaving stream.
754778
See also [`ReadableStreamInterface`](#readablestreaminterface) and
755779
[`WritableStreamInterface`](#writablestreaminterface) for more details.
756780

781+
## Creating streams
782+
783+
ReactPHP uses the concept of "streams" throughout its ecosystem, so that
784+
many higher-level consumers of this package only deal with
785+
[stream usage](#stream-usage).
786+
This implies that stream instances are most often created within some
787+
higher-level components and many consumers never actually have to deal with
788+
creating a stream instance.
789+
790+
* Use [react/socket](https://github.com/reactphp/socket)
791+
if you want to accept incoming or establish outgoing plaintext TCP/IP or
792+
secure TLS socket connection streams.
793+
* Use [react/http](https://github.com/reactphp/http)
794+
if you want to receive an incoming HTTP request body streams.
795+
* Use [react/child-process](https://github.com/reactphp/child-process)
796+
if you want to communicate with child processes via process pipes such as
797+
STDIN, STDOUT, STDERR etc.
798+
* Use experimental [react/filesystem](https://github.com/reactphp/filesystem)
799+
if you want to read from / write to the filesystem.
800+
* See also the last chapter for [more real-world applications](#more).
801+
802+
However, if you are writing a lower-level component or want to create a stream
803+
instance from a stream resource, then the following chapter is for you.
804+
805+
> Note that the following examples use `fopen()` and `stream_socket_client()`
806+
for illustration purposes only.
807+
These functions SHOULD NOT be used in a truly async program because each call
808+
may take several seconds to complete and would block the EventLoop otherwise.
809+
Additionally, the `fopen()` call will return a file handle on some platforms
810+
which may or may not be supported by all EventLoop implementations.
811+
As an alternative, you may want to use higher-level libraries listed above.
812+
757813
### ReadableResourceStream
758814

759815
The `ReadableResourceStream` is a concrete implementation of the
@@ -819,6 +875,12 @@ mean it reached EOF.
819875
$stream = new ReadableResourceStream(STDIN, $loop, 8192);
820876
```
821877

878+
> PHP bug warning: If the PHP process has explicitly been started without a
879+
`STDIN` stream, then trying to read from `STDIN` may return data from
880+
another stream resource. This does not happen if you start this with an empty
881+
stream like `php test.php < /dev/null` instead of `php test.php <&-`.
882+
See [#81](https://github.com/reactphp/stream/issues/81) for more details.
883+
822884
### WritableResourceStream
823885

824886
The `WritableResourceStream` is a concrete implementation of the
@@ -1032,17 +1094,27 @@ $through->write(2);
10321094
```
10331095

10341096
## Usage
1097+
1098+
The following example can be used to pipe the contents of a source file into
1099+
a destination file without having to ever read the whole file into memory:
1100+
10351101
```php
1036-
$loop = React\EventLoop\Factory::create();
1102+
$loop = new React\EventLoop\StreamSelectLoop::create();
10371103

1038-
$source = new React\Stream\ReadableResourceStream(fopen('omg.txt', 'r'), $loop);
1039-
$dest = new React\Stream\WritableResourceStream(fopen('wtf.txt', 'w'), $loop);
1104+
$source = new React\Stream\ReadableResourceStream(fopen('source.txt', 'r'), $loop);
1105+
$dest = new React\Stream\WritableResourceStream(fopen('destination.txt', 'w'), $loop);
10401106

1041-
$source->pipe($dest);
1107+
$source->pipe($dest);
10421108

1043-
$loop->run();
1109+
$loop->run();
10441110
```
10451111

1112+
> Note that this example uses `fopen()` for illustration purposes only.
1113+
This should not be used in a truly async program because the filesystem is
1114+
inherently blocking and each call could potentially take several seconds.
1115+
See also [creating streams](#creating-streams) for more sophisticated
1116+
examples.
1117+
10461118
## Install
10471119

10481120
The recommended way to install this library is [through Composer](http://getcomposer.org).
@@ -1079,3 +1151,11 @@ $ php vendor/bin/phpunit
10791151
## License
10801152

10811153
MIT, see [LICENSE file](LICENSE).
1154+
1155+
## More
1156+
1157+
* See [creating streams](#creating-streams) for more information on how streams
1158+
are created in real-world applications.
1159+
* See our [users wiki](https://github.com/reactphp/react/wiki/Users) and the
1160+
[dependents on Packagist](https://packagist.org/packages/react/stream/dependents)
1161+
for a list of packages that use streams in real-world applications.

0 commit comments

Comments
 (0)