Subversion Repositories php-qbpwcf

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 liveuser 1
# Stream
2
 
3
[![Build Status](https://travis-ci.org/reactphp/stream.svg?branch=master)](https://travis-ci.org/reactphp/stream)
4
 
5
Event-driven readable and writable streams for non-blocking I/O in [ReactPHP](https://reactphp.org/).
6
 
7
In order to make the [EventLoop](https://github.com/reactphp/event-loop)
8
easier to use, this component introduces the powerful concept of "streams".
9
Streams allow you to efficiently process huge amounts of data (such as a multi
10
Gigabyte file download) in small chunks without having to store everything in
11
memory at once.
12
They are very similar to the streams found in PHP itself,
13
but have an interface more suited for async, non-blocking I/O.
14
 
15
**Table of contents**
16
 
17
* [Stream usage](#stream-usage)
18
  * [ReadableStreamInterface](#readablestreaminterface)
19
    * [data event](#data-event)
20
    * [end event](#end-event)
21
    * [error event](#error-event)
22
    * [close event](#close-event)
23
    * [isReadable()](#isreadable)
24
    * [pause()](#pause)
25
    * [resume()](#resume)
26
    * [pipe()](#pipe)
27
    * [close()](#close)
28
  * [WritableStreamInterface](#writablestreaminterface)
29
    * [drain event](#drain-event)
30
    * [pipe event](#pipe-event)
31
    * [error event](#error-event-1)
32
    * [close event](#close-event-1)
33
    * [isWritable()](#iswritable)
34
    * [write()](#write)
35
    * [end()](#end)
36
    * [close()](#close-1)
37
  * [DuplexStreamInterface](#duplexstreaminterface)
38
* [Creating streams](#creating-streams)
39
  * [ReadableResourceStream](#readableresourcestream)
40
  * [WritableResourceStream](#writableresourcestream)
41
  * [DuplexResourceStream](#duplexresourcestream)
42
  * [ThroughStream](#throughstream)
43
  * [CompositeStream](#compositestream)
44
* [Usage](#usage)
45
* [Install](#install)
46
* [Tests](#tests)
47
* [License](#license)
48
* [More](#more)
49
 
50
## Stream usage
51
 
52
ReactPHP uses the concept of "streams" throughout its ecosystem to provide a
53
consistent higher-level abstraction for processing streams of arbitrary data
54
contents and size.
55
While a stream itself is a quite low-level concept, it can be used as a powerful
56
abstraction to build higher-level components and protocols on top.
57
 
58
If you're new to this concept, it helps to think of them as a water pipe:
59
You can consume water from a source or you can produce water and forward (pipe)
60
it to any destination (sink).
61
 
62
Similarly, streams can either be
63
 
64
* readable (such as `STDIN` terminal input) or
65
* writable (such as `STDOUT` terminal output) or
66
* duplex (both readable *and* writable, such as a TCP/IP connection)
67
 
68
Accordingly, this package defines the following three interfaces
69
 
70
* [`ReadableStreamInterface`](#readablestreaminterface)
71
* [`WritableStreamInterface`](#writablestreaminterface)
72
* [`DuplexStreamInterface`](#duplexstreaminterface)
73
 
74
### ReadableStreamInterface
75
 
76
The `ReadableStreamInterface` is responsible for providing an interface for
77
read-only streams and the readable side of duplex streams.
78
 
79
Besides defining a few methods, this interface also implements the
80
`EventEmitterInterface` which allows you to react to certain events.
81
 
82
The event callback functions MUST be a valid `callable` that obeys strict
83
parameter definitions and MUST accept event parameters exactly as documented.
84
The event callback functions MUST NOT throw an `Exception`.
85
The return value of the event callback functions will be ignored and has no
86
effect, so for performance reasons you're recommended to not return any
87
excessive data structures.
88
 
89
Every implementation of this interface MUST follow these event semantics in
90
order to be considered a well-behaving stream.
91
 
92
> Note that higher-level implementations of this interface may choose to
93
  define additional events with dedicated semantics not defined as part of
94
  this low-level stream specification. Conformance with these event semantics
95
  is out of scope for this interface, so you may also have to refer to the
96
  documentation of such a higher-level implementation.
97
 
98
#### data event
99
 
100
The `data` event will be emitted whenever some data was read/received
101
from this source stream.
102
The event receives a single mixed argument for incoming data.
103
 
104
```php
105
$stream->on('data', function ($data) {
106
    echo $data;
107
});
108
```
109
 
110
This event MAY be emitted any number of times, which may be zero times if
111
this stream does not send any data at all.
112
It SHOULD not be emitted after an `end` or `close` event.
113
 
114
The given `$data` argument may be of mixed type, but it's usually
115
recommended it SHOULD be a `string` value or MAY use a type that allows
116
representation as a `string` for maximum compatibility.
117
 
118
Many common streams (such as a TCP/IP connection or a file-based stream)
119
will emit the raw (binary) payload data that is received over the wire as
120
chunks of `string` values.
121
 
122
Due to the stream-based nature of this, the sender may send any number
123
of chunks with varying sizes. There are no guarantees that these chunks
124
will be received with the exact same framing the sender intended to send.
125
In other words, many lower-level protocols (such as TCP/IP) transfer the
126
data in chunks that may be anywhere between single-byte values to several
127
dozens of kilobytes. You may want to apply a higher-level protocol to
128
these low-level data chunks in order to achieve proper message framing.
129
 
130
#### end event
131
 
132
The `end` event will be emitted once the source stream has successfully
133
reached the end of the stream (EOF).
134
 
135
```php
136
$stream->on('end', function () {
137
    echo 'END';
138
});
139
```
140
 
141
This event SHOULD be emitted once or never at all, depending on whether
142
a successful end was detected.
143
It SHOULD NOT be emitted after a previous `end` or `close` event.
144
It MUST NOT be emitted if the stream closes due to a non-successful
145
end, such as after a previous `error` event.
146
 
147
After the stream is ended, it MUST switch to non-readable mode,
148
see also `isReadable()`.
149
 
150
This event will only be emitted if the *end* was reached successfully,
151
not if the stream was interrupted by an unrecoverable error or explicitly
152
closed. Not all streams know this concept of a "successful end".
153
Many use-cases involve detecting when the stream closes (terminates)
154
instead, in this case you should use the `close` event.
155
After the stream emits an `end` event, it SHOULD usually be followed by a
156
`close` event.
157
 
158
Many common streams (such as a TCP/IP connection or a file-based stream)
159
will emit this event if either the remote side closes the connection or
160
a file handle was successfully read until reaching its end (EOF).
161
 
162
Note that this event should not be confused with the `end()` method.
163
This event defines a successful end *reading* from a source stream, while
164
the `end()` method defines *writing* a successful end to a destination
165
stream.
166
 
167
#### error event
168
 
169
The `error` event will be emitted once a fatal error occurs, usually while
170
trying to read from this stream.
171
The event receives a single `Exception` argument for the error instance.
172
 
173
```php
174
$server->on('error', function (Exception $e) {
175
    echo 'Error: ' . $e->getMessage() . PHP_EOL;
176
});
177
```
178
 
179
This event SHOULD be emitted once the stream detects a fatal error, such
180
as a fatal transmission error or after an unexpected `data` or premature
181
`end` event.
182
It SHOULD NOT be emitted after a previous `error`, `end` or `close` event.
183
It MUST NOT be emitted if this is not a fatal error condition, such as
184
a temporary network issue that did not cause any data to be lost.
185
 
186
After the stream errors, it MUST close the stream and SHOULD thus be
187
followed by a `close` event and then switch to non-readable mode, see
188
also `close()` and `isReadable()`.
189
 
190
Many common streams (such as a TCP/IP connection or a file-based stream)
191
only deal with data transmission and do not make assumption about data
192
boundaries (such as unexpected `data` or premature `end` events).
193
In other words, many lower-level protocols (such as TCP/IP) may choose
194
to only emit this for a fatal transmission error once and will then
195
close (terminate) the stream in response.
196
 
197
If this stream is a `DuplexStreamInterface`, you should also notice
198
how the writable side of the stream also implements an `error` event.
199
In other words, an error may occur while either reading or writing the
200
stream which should result in the same error processing.
201
 
202
#### close event
203
 
204
The `close` event will be emitted once the stream closes (terminates).
205
 
206
```php
207
$stream->on('close', function () {
208
    echo 'CLOSED';
209
});
210
```
211
 
212
This event SHOULD be emitted once or never at all, depending on whether
213
the stream ever terminates.
214
It SHOULD NOT be emitted after a previous `close` event.
215
 
216
After the stream is closed, it MUST switch to non-readable mode,
217
see also `isReadable()`.
218
 
219
Unlike the `end` event, this event SHOULD be emitted whenever the stream
220
closes, irrespective of whether this happens implicitly due to an
221
unrecoverable error or explicitly when either side closes the stream.
222
If you only want to detect a *successful* end, you should use the `end`
223
event instead.
224
 
225
Many common streams (such as a TCP/IP connection or a file-based stream)
226
will likely choose to emit this event after reading a *successful* `end`
227
event or after a fatal transmission `error` event.
228
 
229
If this stream is a `DuplexStreamInterface`, you should also notice
230
how the writable side of the stream also implements a `close` event.
231
In other words, after receiving this event, the stream MUST switch into
232
non-writable AND non-readable mode, see also `isWritable()`.
233
Note that this event should not be confused with the `end` event.
234
 
235
#### isReadable()
236
 
237
The `isReadable(): bool` method can be used to
238
check whether this stream is in a readable state (not closed already).
239
 
240
This method can be used to check if the stream still accepts incoming
241
data events or if it is ended or closed already.
242
Once the stream is non-readable, no further `data` or `end` events SHOULD
243
be emitted.
244
 
245
```php
246
assert($stream->isReadable() === false);
247
 
248
$stream->on('data', assertNeverCalled());
249
$stream->on('end', assertNeverCalled());
250
```
251
 
252
A successfully opened stream always MUST start in readable mode.
253
 
254
Once the stream ends or closes, it MUST switch to non-readable mode.
255
This can happen any time, explicitly through `close()` or
256
implicitly due to a remote close or an unrecoverable transmission error.
257
Once a stream has switched to non-readable mode, it MUST NOT transition
258
back to readable mode.
259
 
260
If this stream is a `DuplexStreamInterface`, you should also notice
261
how the writable side of the stream also implements an `isWritable()`
262
method. Unless this is a half-open duplex stream, they SHOULD usually
263
have the same return value.
264
 
265
#### pause()
266
 
267
The `pause(): void` method can be used to
268
pause reading incoming data events.
269
 
270
Removes the data source file descriptor from the event loop. This
271
allows you to throttle incoming data.
272
 
273
Unless otherwise noted, a successfully opened stream SHOULD NOT start
274
in paused state.
275
 
276
Once the stream is paused, no futher `data` or `end` events SHOULD
277
be emitted.
278
 
279
```php
280
$stream->pause();
281
 
282
$stream->on('data', assertShouldNeverCalled());
283
$stream->on('end', assertShouldNeverCalled());
284
```
285
 
286
This method is advisory-only, though generally not recommended, the
287
stream MAY continue emitting `data` events.
288
 
289
You can continue processing events by calling `resume()` again.
290
 
291
Note that both methods can be called any number of times, in particular
292
calling `pause()` more than once SHOULD NOT have any effect.
293
 
294
See also `resume()`.
295
 
296
#### resume()
297
 
298
The `resume(): void` method can be used to
299
resume reading incoming data events.
300
 
301
Re-attach the data source after a previous `pause()`.
302
 
303
```php
304
$stream->pause();
305
 
306
$loop->addTimer(1.0, function () use ($stream) {
307
    $stream->resume();
308
});
309
```
310
 
311
Note that both methods can be called any number of times, in particular
312
calling `resume()` without a prior `pause()` SHOULD NOT have any effect.
313
 
314
See also `pause()`.
315
 
316
#### pipe()
317
 
318
The `pipe(WritableStreamInterface $dest, array $options = [])` method can be used to
319
pipe all the data from this readable source into the given writable destination.
320
 
321
Automatically sends all incoming data to the destination.
322
Automatically throttles the source based on what the destination can handle.
323
 
324
```php
325
$source->pipe($dest);
326
```
327
 
328
Similarly, you can also pipe an instance implementing `DuplexStreamInterface`
329
into itself in order to write back all the data that is received.
330
This may be a useful feature for a TCP/IP echo service:
331
 
332
```php
333
$connection->pipe($connection);
334
```
335
 
336
This method returns the destination stream as-is, which can be used to
337
set up chains of piped streams:
338
 
339
```php
340
$source->pipe($decodeGzip)->pipe($filterBadWords)->pipe($dest);
341
```
342
 
343
By default, this will call `end()` on the destination stream once the
344
source stream emits an `end` event. This can be disabled like this:
345
 
346
```php
347
$source->pipe($dest, array('end' => false));
348
```
349
 
350
Note that this only applies to the `end` event.
351
If an `error` or explicit `close` event happens on the source stream,
352
you'll have to manually close the destination stream:
353
 
354
```php
355
$source->pipe($dest);
356
$source->on('close', function () use ($dest) {
357
    $dest->end('BYE!');
358
});
359
```
360
 
361
If the source stream is not readable (closed state), then this is a NO-OP.
362
 
363
```php
364
$source->close();
365
$source->pipe($dest); // NO-OP
366
```
367
 
368
If the destinantion stream is not writable (closed state), then this will simply
369
throttle (pause) the source stream:
370
 
371
```php
372
$dest->close();
373
$source->pipe($dest); // calls $source->pause()
374
```
375
 
376
Similarly, if the destination stream is closed while the pipe is still
377
active, it will also throttle (pause) the source stream:
378
 
379
```php
380
$source->pipe($dest);
381
$dest->close(); // calls $source->pause()
382
```
383
 
384
Once the pipe is set up successfully, the destination stream MUST emit
385
a `pipe` event with this source stream an event argument.
386
 
387
#### close()
388
 
389
The `close(): void` method can be used to
390
close the stream (forcefully).
391
 
392
This method can be used to (forcefully) close the stream.
393
 
394
```php
395
$stream->close();
396
```
397
 
398
Once the stream is closed, it SHOULD emit a `close` event.
399
Note that this event SHOULD NOT be emitted more than once, in particular
400
if this method is called multiple times.
401
 
402
After calling this method, the stream MUST switch into a non-readable
403
mode, see also `isReadable()`.
404
This means that no further `data` or `end` events SHOULD be emitted.
405
 
406
```php
407
$stream->close();
408
assert($stream->isReadable() === false);
409
 
410
$stream->on('data', assertNeverCalled());
411
$stream->on('end', assertNeverCalled());
412
```
413
 
414
If this stream is a `DuplexStreamInterface`, you should also notice
415
how the writable side of the stream also implements a `close()` method.
416
In other words, after calling this method, the stream MUST switch into
417
non-writable AND non-readable mode, see also `isWritable()`.
418
Note that this method should not be confused with the `end()` method.
419
 
420
### WritableStreamInterface
421
 
422
The `WritableStreamInterface` is responsible for providing an interface for
423
write-only streams and the writable side of duplex streams.
424
 
425
Besides defining a few methods, this interface also implements the
426
`EventEmitterInterface` which allows you to react to certain events.
427
 
428
The event callback functions MUST be a valid `callable` that obeys strict
429
parameter definitions and MUST accept event parameters exactly as documented.
430
The event callback functions MUST NOT throw an `Exception`.
431
The return value of the event callback functions will be ignored and has no
432
effect, so for performance reasons you're recommended to not return any
433
excessive data structures.
434
 
435
Every implementation of this interface MUST follow these event semantics in
436
order to be considered a well-behaving stream.
437
 
438
> Note that higher-level implementations of this interface may choose to
439
  define additional events with dedicated semantics not defined as part of
440
  this low-level stream specification. Conformance with these event semantics
441
  is out of scope for this interface, so you may also have to refer to the
442
  documentation of such a higher-level implementation.
443
 
444
#### drain event
445
 
446
The `drain` event will be emitted whenever the write buffer became full
447
previously and is now ready to accept more data.
448
 
449
```php
450
$stream->on('drain', function () use ($stream) {
451
    echo 'Stream is now ready to accept more data';
452
});
453
```
454
 
455
This event SHOULD be emitted once every time the buffer became full
456
previously and is now ready to accept more data.
457
In other words, this event MAY be emitted any number of times, which may
458
be zero times if the buffer never became full in the first place.
459
This event SHOULD NOT be emitted if the buffer has not become full
460
previously.
461
 
462
This event is mostly used internally, see also `write()` for more details.
463
 
464
#### pipe event
465
 
466
The `pipe` event will be emitted whenever a readable stream is `pipe()`d
467
into this stream.
468
The event receives a single `ReadableStreamInterface` argument for the
469
source stream.
470
 
471
```php
472
$stream->on('pipe', function (ReadableStreamInterface $source) use ($stream) {
473
    echo 'Now receiving piped data';
474
 
475
    // explicitly close target if source emits an error
476
    $source->on('error', function () use ($stream) {
477
        $stream->close();
478
    });
479
});
480
 
481
$source->pipe($stream);
482
```
483
 
484
This event MUST be emitted once for each readable stream that is
485
successfully piped into this destination stream.
486
In other words, this event MAY be emitted any number of times, which may
487
be zero times if no stream is ever piped into this stream.
488
This event MUST NOT be emitted if either the source is not readable
489
(closed already) or this destination is not writable (closed already).
490
 
491
This event is mostly used internally, see also `pipe()` for more details.
492
 
493
#### error event
494
 
495
The `error` event will be emitted once a fatal error occurs, usually while
496
trying to write to this stream.
497
The event receives a single `Exception` argument for the error instance.
498
 
499
```php
500
$stream->on('error', function (Exception $e) {
501
    echo 'Error: ' . $e->getMessage() . PHP_EOL;
502
});
503
```
504
 
505
This event SHOULD be emitted once the stream detects a fatal error, such
506
as a fatal transmission error.
507
It SHOULD NOT be emitted after a previous `error` or `close` event.
508
It MUST NOT be emitted if this is not a fatal error condition, such as
509
a temporary network issue that did not cause any data to be lost.
510
 
511
After the stream errors, it MUST close the stream and SHOULD thus be
512
followed by a `close` event and then switch to non-writable mode, see
513
also `close()` and `isWritable()`.
514
 
515
Many common streams (such as a TCP/IP connection or a file-based stream)
516
only deal with data transmission and may choose
517
to only emit this for a fatal transmission error once and will then
518
close (terminate) the stream in response.
519
 
520
If this stream is a `DuplexStreamInterface`, you should also notice
521
how the readable side of the stream also implements an `error` event.
522
In other words, an error may occur while either reading or writing the
523
stream which should result in the same error processing.
524
 
525
#### close event
526
 
527
The `close` event will be emitted once the stream closes (terminates).
528
 
529
```php
530
$stream->on('close', function () {
531
    echo 'CLOSED';
532
});
533
```
534
 
535
This event SHOULD be emitted once or never at all, depending on whether
536
the stream ever terminates.
537
It SHOULD NOT be emitted after a previous `close` event.
538
 
539
After the stream is closed, it MUST switch to non-writable mode,
540
see also `isWritable()`.
541
 
542
This event SHOULD be emitted whenever the stream closes, irrespective of
543
whether this happens implicitly due to an unrecoverable error or
544
explicitly when either side closes the stream.
545
 
546
Many common streams (such as a TCP/IP connection or a file-based stream)
547
will likely choose to emit this event after flushing the buffer from
548
the `end()` method, after receiving a *successful* `end` event or after
549
a fatal transmission `error` event.
550
 
551
If this stream is a `DuplexStreamInterface`, you should also notice
552
how the readable side of the stream also implements a `close` event.
553
In other words, after receiving this event, the stream MUST switch into
554
non-writable AND non-readable mode, see also `isReadable()`.
555
Note that this event should not be confused with the `end` event.
556
 
557
#### isWritable()
558
 
559
The `isWritable(): bool` method can be used to
560
check whether this stream is in a writable state (not closed already).
561
 
562
This method can be used to check if the stream still accepts writing
563
any data or if it is ended or closed already.
564
Writing any data to a non-writable stream is a NO-OP:
565
 
566
```php
567
assert($stream->isWritable() === false);
568
 
569
$stream->write('end'); // NO-OP
570
$stream->end('end'); // NO-OP
571
```
572
 
573
A successfully opened stream always MUST start in writable mode.
574
 
575
Once the stream ends or closes, it MUST switch to non-writable mode.
576
This can happen any time, explicitly through `end()` or `close()` or
577
implicitly due to a remote close or an unrecoverable transmission error.
578
Once a stream has switched to non-writable mode, it MUST NOT transition
579
back to writable mode.
580
 
581
If this stream is a `DuplexStreamInterface`, you should also notice
582
how the readable side of the stream also implements an `isReadable()`
583
method. Unless this is a half-open duplex stream, they SHOULD usually
584
have the same return value.
585
 
586
#### write()
587
 
588
The `write(mixed $data): bool` method can be used to
589
write some data into the stream.
590
 
591
A successful write MUST be confirmed with a boolean `true`, which means
592
that either the data was written (flushed) immediately or is buffered and
593
scheduled for a future write. Note that this interface gives you no
594
control over explicitly flushing the buffered data, as finding the
595
appropriate time for this is beyond the scope of this interface and left
596
up to the implementation of this interface.
597
 
598
Many common streams (such as a TCP/IP connection or file-based stream)
599
may choose to buffer all given data and schedule a future flush by using
600
an underlying EventLoop to check when the resource is actually writable.
601
 
602
If a stream cannot handle writing (or flushing) the data, it SHOULD emit
603
an `error` event and MAY `close()` the stream if it can not recover from
604
this error.
605
 
606
If the internal buffer is full after adding `$data`, then `write()`
607
SHOULD return `false`, indicating that the caller should stop sending
608
data until the buffer drains.
609
The stream SHOULD send a `drain` event once the buffer is ready to accept
610
more data.
611
 
612
Similarly, if the the stream is not writable (already in a closed state)
613
it MUST NOT process the given `$data` and SHOULD return `false`,
614
indicating that the caller should stop sending data.
615
 
616
The given `$data` argument MAY be of mixed type, but it's usually
617
recommended it SHOULD be a `string` value or MAY use a type that allows
618
representation as a `string` for maximum compatibility.
619
 
620
Many common streams (such as a TCP/IP connection or a file-based stream)
621
will only accept the raw (binary) payload data that is transferred over
622
the wire as chunks of `string` values.
623
 
624
Due to the stream-based nature of this, the sender may send any number
625
of chunks with varying sizes. There are no guarantees that these chunks
626
will be received with the exact same framing the sender intended to send.
627
In other words, many lower-level protocols (such as TCP/IP) transfer the
628
data in chunks that may be anywhere between single-byte values to several
629
dozens of kilobytes. You may want to apply a higher-level protocol to
630
these low-level data chunks in order to achieve proper message framing.
631
 
632
#### end()
633
 
634
The `end(mixed $data = null): void` method can be used to
635
successfully end the stream (after optionally sending some final data).
636
 
637
This method can be used to successfully end the stream, i.e. close
638
the stream after sending out all data that is currently buffered.
639
 
640
```php
641
$stream->write('hello');
642
$stream->write('world');
643
$stream->end();
644
```
645
 
646
If there's no data currently buffered and nothing to be flushed, then
647
this method MAY `close()` the stream immediately.
648
 
649
If there's still data in the buffer that needs to be flushed first, then
650
this method SHOULD try to write out this data and only then `close()`
651
the stream.
652
Once the stream is closed, it SHOULD emit a `close` event.
653
 
654
Note that this interface gives you no control over explicitly flushing
655
the buffered data, as finding the appropriate time for this is beyond the
656
scope of this interface and left up to the implementation of this
657
interface.
658
 
659
Many common streams (such as a TCP/IP connection or file-based stream)
660
may choose to buffer all given data and schedule a future flush by using
661
an underlying EventLoop to check when the resource is actually writable.
662
 
663
You can optionally pass some final data that is written to the stream
664
before ending the stream. If a non-`null` value is given as `$data`, then
665
this method will behave just like calling `write($data)` before ending
666
with no data.
667
 
668
```php
669
// shorter version
670
$stream->end('bye');
671
 
672
// same as longer version
673
$stream->write('bye');
674
$stream->end();
675
```
676
 
677
After calling this method, the stream MUST switch into a non-writable
678
mode, see also `isWritable()`.
679
This means that no further writes are possible, so any additional
680
`write()` or `end()` calls have no effect.
681
 
682
```php
683
$stream->end();
684
assert($stream->isWritable() === false);
685
 
686
$stream->write('nope'); // NO-OP
687
$stream->end(); // NO-OP
688
```
689
 
690
If this stream is a `DuplexStreamInterface`, calling this method SHOULD
691
also end its readable side, unless the stream supports half-open mode.
692
In other words, after calling this method, these streams SHOULD switch
693
into non-writable AND non-readable mode, see also `isReadable()`.
694
This implies that in this case, the stream SHOULD NOT emit any `data`
695
or `end` events anymore.
696
Streams MAY choose to use the `pause()` method logic for this, but
697
special care may have to be taken to ensure a following call to the
698
`resume()` method SHOULD NOT continue emitting readable events.
699
 
700
Note that this method should not be confused with the `close()` method.
701
 
702
#### close()
703
 
704
The `close(): void` method can be used to
705
close the stream (forcefully).
706
 
707
This method can be used to forcefully close the stream, i.e. close
708
the stream without waiting for any buffered data to be flushed.
709
If there's still data in the buffer, this data SHOULD be discarded.
710
 
711
```php
712
$stream->close();
713
```
714
 
715
Once the stream is closed, it SHOULD emit a `close` event.
716
Note that this event SHOULD NOT be emitted more than once, in particular
717
if this method is called multiple times.
718
 
719
After calling this method, the stream MUST switch into a non-writable
720
mode, see also `isWritable()`.
721
This means that no further writes are possible, so any additional
722
`write()` or `end()` calls have no effect.
723
 
724
```php
725
$stream->close();
726
assert($stream->isWritable() === false);
727
 
728
$stream->write('nope'); // NO-OP
729
$stream->end(); // NO-OP
730
```
731
 
732
Note that this method should not be confused with the `end()` method.
733
Unlike the `end()` method, this method does not take care of any existing
734
buffers and simply discards any buffer contents.
735
Likewise, this method may also be called after calling `end()` on a
736
stream in order to stop waiting for the stream to flush its final data.
737
 
738
```php
739
$stream->end();
740
$loop->addTimer(1.0, function () use ($stream) {
741
    $stream->close();
742
});
743
```
744
 
745
If this stream is a `DuplexStreamInterface`, you should also notice
746
how the readable side of the stream also implements a `close()` method.
747
In other words, after calling this method, the stream MUST switch into
748
non-writable AND non-readable mode, see also `isReadable()`.
749
 
750
### DuplexStreamInterface
751
 
752
The `DuplexStreamInterface` is responsible for providing an interface for
753
duplex streams (both readable and writable).
754
 
755
It builds on top of the existing interfaces for readable and writable streams
756
and follows the exact same method and event semantics.
757
If you're new to this concept, you should look into the
758
`ReadableStreamInterface` and `WritableStreamInterface` first.
759
 
760
Besides defining a few methods, this interface also implements the
761
`EventEmitterInterface` which allows you to react to the same events defined
762
on the `ReadbleStreamInterface` and `WritableStreamInterface`.
763
 
764
The event callback functions MUST be a valid `callable` that obeys strict
765
parameter definitions and MUST accept event parameters exactly as documented.
766
The event callback functions MUST NOT throw an `Exception`.
767
The return value of the event callback functions will be ignored and has no
768
effect, so for performance reasons you're recommended to not return any
769
excessive data structures.
770
 
771
Every implementation of this interface MUST follow these event semantics in
772
order to be considered a well-behaving stream.
773
 
774
> Note that higher-level implementations of this interface may choose to
775
  define additional events with dedicated semantics not defined as part of
776
  this low-level stream specification. Conformance with these event semantics
777
  is out of scope for this interface, so you may also have to refer to the
778
  documentation of such a higher-level implementation.
779
 
780
See also [`ReadableStreamInterface`](#readablestreaminterface) and
781
[`WritableStreamInterface`](#writablestreaminterface) for more details.
782
 
783
## Creating streams
784
 
785
ReactPHP uses the concept of "streams" throughout its ecosystem, so that
786
many higher-level consumers of this package only deal with
787
[stream usage](#stream-usage).
788
This implies that stream instances are most often created within some
789
higher-level components and many consumers never actually have to deal with
790
creating a stream instance.
791
 
792
* Use [react/socket](https://github.com/reactphp/socket)
793
  if you want to accept incoming or establish outgoing plaintext TCP/IP or
794
  secure TLS socket connection streams.
795
* Use [react/http](https://github.com/reactphp/http)
796
  if you want to receive an incoming HTTP request body streams.
797
* Use [react/child-process](https://github.com/reactphp/child-process)
798
  if you want to communicate with child processes via process pipes such as
799
  STDIN, STDOUT, STDERR etc.
800
* Use experimental [react/filesystem](https://github.com/reactphp/filesystem)
801
  if you want to read from / write to the filesystem.
802
* See also the last chapter for [more real-world applications](#more).
803
 
804
However, if you are writing a lower-level component or want to create a stream
805
instance from a stream resource, then the following chapter is for you.
806
 
807
> Note that the following examples use `fopen()` and `stream_socket_client()`
808
  for illustration purposes only.
809
  These functions SHOULD NOT be used in a truly async program because each call
810
  may take several seconds to complete and would block the EventLoop otherwise.
811
  Additionally, the `fopen()` call will return a file handle on some platforms
812
  which may or may not be supported by all EventLoop implementations.
813
  As an alternative, you may want to use higher-level libraries listed above.
814
 
815
### ReadableResourceStream
816
 
817
The `ReadableResourceStream` is a concrete implementation of the
818
[`ReadableStreamInterface`](#readablestreaminterface) for PHP's stream resources.
819
 
820
This can be used to represent a read-only resource like a file stream opened in
821
readable mode or a stream such as `STDIN`:
822
 
823
```php
824
$stream = new ReadableResourceStream(STDIN, $loop);
825
$stream->on('data', function ($chunk) {
826
    echo $chunk;
827
});
828
$stream->on('end', function () {
829
    echo 'END';
830
});
831
```
832
 
833
See also [`ReadableStreamInterface`](#readablestreaminterface) for more details.
834
 
835
The first parameter given to the constructor MUST be a valid stream resource
836
that is opened in reading mode (e.g. `fopen()` mode `r`).
837
Otherwise, it will throw an `InvalidArgumentException`:
838
 
839
```php
840
// throws InvalidArgumentException
841
$stream = new ReadableResourceStream(false, $loop);
842
```
843
 
844
See also the [`DuplexResourceStream`](#readableresourcestream) for read-and-write
845
stream resources otherwise.
846
 
847
Internally, this class tries to enable non-blocking mode on the stream resource
848
which may not be supported for all stream resources.
849
Most notably, this is not supported by pipes on Windows (STDIN etc.).
850
If this fails, it will throw a `RuntimeException`:
851
 
852
```php
853
// throws RuntimeException on Windows
854
$stream = new ReadableResourceStream(STDIN, $loop);
855
```
856
 
857
Once the constructor is called with a valid stream resource, this class will
858
take care of the underlying stream resource.
859
You SHOULD only use its public API and SHOULD NOT interfere with the underlying
860
stream resource manually.
861
 
862
This class takes an optional `int|null $readChunkSize` parameter that controls
863
the maximum buffer size in bytes to read at once from the stream.
864
You can use a `null` value here in order to apply its default value.
865
This value SHOULD NOT be changed unless you know what you're doing.
866
This can be a positive number which means that up to X bytes will be read
867
at once from the underlying stream resource. Note that the actual number
868
of bytes read may be lower if the stream resource has less than X bytes
869
currently available.
870
This can be `-1` which means "read everything available" from the
871
underlying stream resource.
872
This should read until the stream resource is not readable anymore
873
(i.e. underlying buffer drained), note that this does not neccessarily
874
mean it reached EOF.
875
 
876
```php
877
$stream = new ReadableResourceStream(STDIN, $loop, 8192);
878
```
879
 
880
> PHP bug warning: If the PHP process has explicitly been started without a
881
  `STDIN` stream, then trying to read from `STDIN` may return data from
882
  another stream resource. This does not happen if you start this with an empty
883
  stream like `php test.php < /dev/null` instead of `php test.php <&-`.
884
  See [#81](https://github.com/reactphp/stream/issues/81) for more details.
885
 
886
### WritableResourceStream
887
 
888
The `WritableResourceStream` is a concrete implementation of the
889
[`WritableStreamInterface`](#writablestreaminterface) for PHP's stream resources.
890
 
891
This can be used to represent a write-only resource like a file stream opened in
892
writable mode or a stream such as `STDOUT` or `STDERR`:
893
 
894
```php
895
$stream = new WritableResourceStream(STDOUT, $loop);
896
$stream->write('hello!');
897
$stream->end();
898
```
899
 
900
See also [`WritableStreamInterface`](#writablestreaminterface) for more details.
901
 
902
The first parameter given to the constructor MUST be a valid stream resource
903
that is opened for writing.
904
Otherwise, it will throw an `InvalidArgumentException`:
905
 
906
```php
907
// throws InvalidArgumentException
908
$stream = new WritableResourceStream(false, $loop);
909
```
910
 
911
See also the [`DuplexResourceStream`](#readableresourcestream) for read-and-write
912
stream resources otherwise.
913
 
914
Internally, this class tries to enable non-blocking mode on the stream resource
915
which may not be supported for all stream resources.
916
Most notably, this is not supported by pipes on Windows (STDOUT, STDERR etc.).
917
If this fails, it will throw a `RuntimeException`:
918
 
919
```php
920
// throws RuntimeException on Windows
921
$stream = new WritableResourceStream(STDOUT, $loop);
922
```
923
 
924
Once the constructor is called with a valid stream resource, this class will
925
take care of the underlying stream resource.
926
You SHOULD only use its public API and SHOULD NOT interfere with the underlying
927
stream resource manually.
928
 
929
Any `write()` calls to this class will not be performed instantly, but will
930
be performed asynchronously, once the EventLoop reports the stream resource is
931
ready to accept data.
932
For this, it uses an in-memory buffer string to collect all outstanding writes.
933
This buffer has a soft-limit applied which defines how much data it is willing
934
to accept before the caller SHOULD stop sending further data.
935
 
936
This class takes an optional `int|null $writeBufferSoftLimit` parameter that controls
937
this maximum buffer size in bytes.
938
You can use a `null` value here in order to apply its default value.
939
This value SHOULD NOT be changed unless you know what you're doing.
940
 
941
```php
942
$stream = new WritableResourceStream(STDOUT, $loop, 8192);
943
```
944
 
945
This class takes an optional `int|null $writeChunkSize` parameter that controls
946
this maximum buffer size in bytes to write at once to the stream.
947
You can use a `null` value here in order to apply its default value.
948
This value SHOULD NOT be changed unless you know what you're doing.
949
This can be a positive number which means that up to X bytes will be written
950
at once to the underlying stream resource. Note that the actual number
951
of bytes written may be lower if the stream resource has less than X bytes
952
currently available.
953
This can be `-1` which means "write everything available" to the
954
underlying stream resource.
955
 
956
```php
957
$stream = new WritableResourceStream(STDOUT, $loop, null, 8192);
958
```
959
 
960
See also [`write()`](#write) for more details.
961
 
962
### DuplexResourceStream
963
 
964
The `DuplexResourceStream` is a concrete implementation of the
965
[`DuplexStreamInterface`](#duplexstreaminterface) for PHP's stream resources.
966
 
967
This can be used to represent a read-and-write resource like a file stream opened
968
in read and write mode mode or a stream such as a TCP/IP connection:
969
 
970
```php
971
$conn = stream_socket_client('tcp://google.com:80');
972
$stream = new DuplexResourceStream($conn, $loop);
973
$stream->write('hello!');
974
$stream->end();
975
```
976
 
977
See also [`DuplexStreamInterface`](#duplexstreaminterface) for more details.
978
 
979
The first parameter given to the constructor MUST be a valid stream resource
980
that is opened for reading *and* writing.
981
Otherwise, it will throw an `InvalidArgumentException`:
982
 
983
```php
984
// throws InvalidArgumentException
985
$stream = new DuplexResourceStream(false, $loop);
986
```
987
 
988
See also the [`ReadableResourceStream`](#readableresourcestream) for read-only
989
and the [`WritableResourceStream`](#writableresourcestream) for write-only
990
stream resources otherwise.
991
 
992
Internally, this class tries to enable non-blocking mode on the stream resource
993
which may not be supported for all stream resources.
994
Most notably, this is not supported by pipes on Windows (STDOUT, STDERR etc.).
995
If this fails, it will throw a `RuntimeException`:
996
 
997
```php
998
// throws RuntimeException on Windows
999
$stream = new DuplexResourceStream(STDOUT, $loop);
1000
```
1001
 
1002
Once the constructor is called with a valid stream resource, this class will
1003
take care of the underlying stream resource.
1004
You SHOULD only use its public API and SHOULD NOT interfere with the underlying
1005
stream resource manually.
1006
 
1007
This class takes an optional `int|null $readChunkSize` parameter that controls
1008
the maximum buffer size in bytes to read at once from the stream.
1009
You can use a `null` value here in order to apply its default value.
1010
This value SHOULD NOT be changed unless you know what you're doing.
1011
This can be a positive number which means that up to X bytes will be read
1012
at once from the underlying stream resource. Note that the actual number
1013
of bytes read may be lower if the stream resource has less than X bytes
1014
currently available.
1015
This can be `-1` which means "read everything available" from the
1016
underlying stream resource.
1017
This should read until the stream resource is not readable anymore
1018
(i.e. underlying buffer drained), note that this does not neccessarily
1019
mean it reached EOF.
1020
 
1021
```php
1022
$conn = stream_socket_client('tcp://google.com:80');
1023
$stream = new DuplexResourceStream($conn, $loop, 8192);
1024
```
1025
 
1026
Any `write()` calls to this class will not be performed instantly, but will
1027
be performed asynchronously, once the EventLoop reports the stream resource is
1028
ready to accept data.
1029
For this, it uses an in-memory buffer string to collect all outstanding writes.
1030
This buffer has a soft-limit applied which defines how much data it is willing
1031
to accept before the caller SHOULD stop sending further data.
1032
 
1033
This class takes another optional `WritableStreamInterface|null $buffer` parameter
1034
that controls this write behavior of this stream.
1035
You can use a `null` value here in order to apply its default value.
1036
This value SHOULD NOT be changed unless you know what you're doing.
1037
 
1038
If you want to change the write buffer soft limit, you can pass an instance of
1039
[`WritableResourceStream`](#writableresourcestream) like this:
1040
 
1041
```php
1042
$conn = stream_socket_client('tcp://google.com:80');
1043
$buffer = new WritableResourceStream($conn, $loop, 8192);
1044
$stream = new DuplexResourceStream($conn, $loop, null, $buffer);
1045
```
1046
 
1047
See also [`WritableResourceStream`](#writableresourcestream) for more details.
1048
 
1049
### ThroughStream
1050
 
1051
The `ThroughStream` implements the
1052
[`DuplexStreamInterface`](#duplexstreaminterface) and will simply pass any data
1053
you write to it through to its readable end.
1054
 
1055
```php
1056
$through = new ThroughStream();
1057
$through->on('data', $this->expectCallableOnceWith('hello'));
1058
 
1059
$through->write('hello');
1060
```
1061
 
1062
Similarly, the [`end()` method](#end) will end the stream and emit an
1063
[`end` event](#end-event) and then [`close()`](#close-1) the stream.
1064
The [`close()` method](#close-1) will close the stream and emit a
1065
[`close` event](#close-event).
1066
Accordingly, this is can also be used in a [`pipe()`](#pipe) context like this:
1067
 
1068
```php
1069
$through = new ThroughStream();
1070
$source->pipe($through)->pipe($dest);
1071
```
1072
 
1073
Optionally, its constructor accepts any callable function which will then be
1074
used to *filter* any data written to it. This function receives a single data
1075
argument as passed to the writable side and must return the data as it will be
1076
passed to its readable end:
1077
 
1078
```php
1079
$through = new ThroughStream('strtoupper');
1080
$source->pipe($through)->pipe($dest);
1081
```
1082
 
1083
Note that this class makes no assumptions about any data types. This can be
1084
used to convert data, for example for transforming any structured data into
1085
a newline-delimited JSON (NDJSON) stream like this:
1086
 
1087
```php
1088
$through = new ThroughStream(function ($data) {
1089
    return json_encode($data) . PHP_EOL;
1090
});
1091
$through->on('data', $this->expectCallableOnceWith("[2, true]\n"));
1092
 
1093
$through->write(array(2, true));
1094
```
1095
 
1096
The callback function is allowed to throw an `Exception`. In this case,
1097
the stream will emit an `error` event and then [`close()`](#close-1) the stream.
1098
 
1099
```php
1100
$through = new ThroughStream(function ($data) {
1101
    if (!is_string($data)) {
1102
        throw new \UnexpectedValueException('Only strings allowed');
1103
    }
1104
    return $data;
1105
});
1106
$through->on('error', $this->expectCallableOnce()));
1107
$through->on('close', $this->expectCallableOnce()));
1108
$through->on('data', $this->expectCallableNever()));
1109
 
1110
$through->write(2);
1111
```
1112
 
1113
### CompositeStream
1114
 
1115
The `CompositeStream` implements the
1116
[`DuplexStreamInterface`](#duplexstreaminterface) and can be used to create a
1117
single duplex stream from two individual streams implementing
1118
[`ReadableStreamInterface`](#readablestreaminterface) and
1119
[`WritableStreamInterface`](#writablestreaminterface) respectively.
1120
 
1121
This is useful for some APIs which may require a single
1122
[`DuplexStreamInterface`](#duplexstreaminterface) or simply because it's often
1123
more convenient to work with a single stream instance like this:
1124
 
1125
```php
1126
$stdin = new ReadableResourceStream(STDIN, $loop);
1127
$stdout = new WritableResourceStream(STDOUT, $loop);
1128
 
1129
$stdio = new CompositeStream($stdin, $stdout);
1130
 
1131
$stdio->on('data', function ($chunk) use ($stdio) {
1132
    $stdio->write('You said: ' . $chunk);
1133
});
1134
```
1135
 
1136
This is a well-behaving stream which forwards all stream events from the
1137
underlying streams and forwards all streams calls to the underlying streams.
1138
 
1139
If you `write()` to the duplex stream, it will simply `write()` to the
1140
writable side and return its status.
1141
 
1142
If you `end()` the duplex stream, it will `end()` the writable side and will
1143
`pause()` the readable side.
1144
 
1145
If you `close()` the duplex stream, both input streams will be closed.
1146
If either of the two input streams emits a `close` event, the duplex stream
1147
will also close.
1148
If either of the two input streams is already closed while constructing the
1149
duplex stream, it will `close()` the other side and return a closed stream.
1150
 
1151
## Usage
1152
 
1153
The following example can be used to pipe the contents of a source file into
1154
a destination file without having to ever read the whole file into memory:
1155
 
1156
```php
1157
$loop = new React\EventLoop\StreamSelectLoop;
1158
 
1159
$source = new React\Stream\ReadableResourceStream(fopen('source.txt', 'r'), $loop);
1160
$dest = new React\Stream\WritableResourceStream(fopen('destination.txt', 'w'), $loop);
1161
 
1162
$source->pipe($dest);
1163
 
1164
$loop->run();
1165
```
1166
 
1167
> Note that this example uses `fopen()` for illustration purposes only.
1168
  This should not be used in a truly async program because the filesystem is
1169
  inherently blocking and each call could potentially take several seconds.
1170
  See also [creating streams](#creating-streams) for more sophisticated
1171
  examples.
1172
 
1173
## Install
1174
 
1175
The recommended way to install this library is [through Composer](https://getcomposer.org).
1176
[New to Composer?](https://getcomposer.org/doc/00-intro.md)
1177
 
1178
This project follows [SemVer](https://semver.org/).
1179
This will install the latest supported version:
1180
 
1181
```bash
1182
$ composer require react/stream:^1.1.1
1183
```
1184
 
1185
See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
1186
 
1187
This project aims to run on any platform and thus does not require any PHP
1188
extensions and supports running on legacy PHP 5.3 through current PHP 7+ and HHVM.
1189
It's *highly recommended to use PHP 7+* for this project due to its vast
1190
performance improvements.
1191
 
1192
## Tests
1193
 
1194
To run the test suite, you first need to clone this repo and then install all
1195
dependencies [through Composer](https://getcomposer.org):
1196
 
1197
```bash
1198
$ composer install
1199
```
1200
 
1201
To run the test suite, go to the project root and run:
1202
 
1203
```bash
1204
$ php vendor/bin/phpunit
1205
```
1206
 
1207
The test suite also contains a number of functional integration tests that rely
1208
on a stable internet connection.
1209
If you do not want to run these, they can simply be skipped like this:
1210
 
1211
```bash
1212
$ php vendor/bin/phpunit --exclude-group internet
1213
```
1214
 
1215
## License
1216
 
1217
MIT, see [LICENSE file](LICENSE).
1218
 
1219
## More
1220
 
1221
* See [creating streams](#creating-streams) for more information on how streams
1222
  are created in real-world applications.
1223
* See our [users wiki](https://github.com/reactphp/react/wiki/Users) and the
1224
  [dependents on Packagist](https://packagist.org/packages/react/stream/dependents)
1225
  for a list of packages that use streams in real-world applications.