Lucky Catch: Lucky O'Toole Vegas Adventure by Deborah Coonts
PHP Streams: Lucky Dip
-
Upload
wez-furlong -
Category
Technology
-
view
8.590 -
download
1
description
Transcript of PHP Streams: Lucky Dip
![Page 2: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/2.jpg)
About the author
• PHP Core Developer since 2001
• Author of the Streams layer
• I hold the title “King” of PECL
• Author of most of PDO and its drivers
• Day-job is developing the fastest MTA on Earth
![Page 3: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/3.jpg)
Lucky Dip!?
• Streams is a big topic area
• Every uses them
• A lot of people misuse them
• tid-bits from basic to advanced level
![Page 4: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/4.jpg)
What is a stream?
• View of some kind of data
• Presented in chunks
• Readable
• Writable
• Sometimes seekable
![Page 5: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/5.jpg)
File based streams
• Most common (include/require)
• Represent data held in a filesystem
![Page 6: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/6.jpg)
Typical file reading code
$fp = fopen(‘myfile.txt’, ‘r’);
while (!feof($fp)) { $data .= fread($fp, 8192);}
$fp = fopen(‘myfile.txt’, ‘r’); $data = fread($fp, filesize(‘myfile.txt’));
![Page 7: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/7.jpg)
Comparisons
file_get_contents() and stream_get_contents()
get all data into a variable
Fastest, most efficient
![Page 8: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/8.jpg)
Comparisons
while (!feof($fp)) fread($fp, 8192)
Reads chunks
Most memory efficient way
8192 matches internal chunk size
![Page 9: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/9.jpg)
Comparisons
while (!feof($fp)) fgets($fp)
Reads lines
Most memory efficient way
Slowest way to read chunks
Slowest way to read whole file
![Page 10: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/10.jpg)
Comparisons
foreach (file($filename) as $line)
Reads lines
Fastest way
Loads whole file into memory
![Page 11: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/11.jpg)
flock()
• Locks a file
• Shared of exclusive
• Advisory
• Only works if everyone uses flock()
• Mandatory on Windows!
• Sounds useful for web apps that use files
![Page 12: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/12.jpg)
Using flock()
Reader:
$fp = fopen($filename, ‘r’);
flock($fp, LOCK_SH);
# it’s now safe to read the file
$data = fread($fp, 8192);
flock($fp, LOCK_UN);
![Page 13: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/13.jpg)
Using flock()
Writer:
$fp = fopen($filename, ‘w+’);
flock($fp, LOCK_EX);
# we’re the only writer now
fwrite($fp, $data);
flock($fp, LOCK_UN);
![Page 14: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/14.jpg)
flock() blocks
• flock() is “safe” because it will block until the lock is obtained
• Blocking is like sleeping
• While you’re asleep, you’re not doing any work
• Sometimes you want to do work while you wait
![Page 15: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/15.jpg)
Using flock()
Non-blocking:
$fp = fopen($filename, ‘w+’);
if (flock($fp, LOCK_EX|LOCK_NB)) {
# we got the lock
} else {
# do something productive while we wait# for the lock
}
![Page 16: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/16.jpg)
flock() summary
• Can be useful to ensure consistency
• Caveat: doesn’t work on most network filesystems
• Caveat: doesn’t work in threaded servers
• ISAPI, NSAPI, win32 apache
• threaded apache 2
• Caveat: some Linux kernels have broken flock()
![Page 17: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/17.jpg)
Network Streams: sockets
• “Wormholes”
• according to the Unix Socket FAQ
• Bi-directional
• data goes both ways
• Differences in behavior from file streams
![Page 18: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/18.jpg)
fsockopen()
An HTTP request:
$fp = fsockopen(‘www.php.net’, 80);
fwrite($fp, “GET / HTTP/1.0\r\n” . “Host: www.php.net\r\n\r\n”);
$data = fread($fp, 8192);
![Page 19: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/19.jpg)
Alternative HTTP request:
$fp = fopen(‘http://www.php.net’, ‘r’);
$data = fread($fp, 8192);
This is an example of a wrapper
![Page 20: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/20.jpg)
Network Streams: feof()
• Common error:
• Assuming that feof() means “connection_closed()”
• feof() returns true when:
• A read fails and the buffer is empty
• or: buffer is empty and no data has been received within the socket timeout
• Lack of data is often a temporary condition for network streams
![Page 21: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/21.jpg)
Short reads, short writes
Another common mistake:
$fp = fopen(‘http://www.php.net’, ‘r’);echo fread($fp, 100000000);fclose($fp);
Reads are non-greedy
Think in terms of 8k chunks
Check the return value from fwrite()!
![Page 22: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/22.jpg)
Speaking the lingo
Common mistake: “PHP hangs!”
$fp = fsockopen(‘www.php.net’, 80);fwrite($fp, “GET / HTTP/1.0\r\n” . “Host: www.php.net\r\n”);$data = fread($fp, 8192);
![Page 23: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/23.jpg)
Sockets block
• Sockets are blocking by default
• Blocking is like sleeping
• Can cause long delays in your scripts
• PHP has 2.5 ways to control them
![Page 24: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/24.jpg)
1. Non-blocking mode
• stream_set_blocking($fp, false);
• Reads/writes will “fail” instead of blocking
• Check the return values from fread() and fwrite()
• zero or zero-length: try again later
• try again means: try sending that data again
• implement your own buffering
• feof() loses meaning
![Page 25: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/25.jpg)
Awful non-blocking code
function get_sock($host, $port) { $s = fsockopen($host, $port); stream_set_blocking($s, false); return $s;}
$hosts[] = get_sock(...); $hosts[] = get_sock(...); $hosts[] = get_sock(...); # repeat 20 times
# read all data without blocking do { foreach ($hosts as $s) echo fread($s, 8192);} while (true);
![Page 26: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/26.jpg)
2. Timeouts
• stream_set_timeout($fp, $sec, $usec);
• Default 60 seconds
• Waits for up-to the timeout period
• Returns data if it is available before then
• Otherwise
• Sets ‘timed_out’ meta data field
• Returns an empty string (or zero)
![Page 27: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/27.jpg)
Non-blocking vs. timeouts
• Timeouts
• Easiest when working with a single socket
• Non-blocking
• Useful for doing multiple things at once
• Painful when using what we’ve seen so far
![Page 28: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/28.jpg)
2.5: stream_select()
• Non-blocking and timeouts combined!
• Sockets don’t have to be non-blocking
• Can wait for read/write/exceptional data
• stream_select() tells you when what you want to do will not block
![Page 29: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/29.jpg)
stream_select()
$fp = fsockopen(‘www.php.net’, 80);fwrite($fp, “GET / HTTP/1.0\r\n” .“Host: www.php.net\r\n\r\n”);# wait up to 2 seconds$n = stream_select($r = array($fp), $w = null, $e = null, 2); if ($n) $data = fread($fp, 8192);else echo “timed out”;
![Page 30: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/30.jpg)
Awful code made nicer
$sites[] = open_site(‘www.php.net’);$sites[] = open_site(‘pecl.php.net’);$sites[] = open_site(...); # repeat 20 times$n = stream_select($r = $sites, $w = null, $e = null, 30);if ($n) foreach ($r as $fp) { $x = fread($fp, 8192); if (strlen($x)) echo $x; else { # it closed unset($sites[array_search($fp, $sites)]); }}
![Page 31: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/31.jpg)
Meta data
• stream_get_meta_data();
• People mis-used it
• The manual says “Hands off!”
• Especially eof and unread_bytes
• “I do not think it means what you think it means”INIGO, The Princess Bride
![Page 32: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/32.jpg)
pipes
• A bit like sockets
• But they’re uni-directional
• data flows only one way
• Often used to pipe the output of one process into another
• popen() and proc_open()
• STDIN, STDOUT, STDERR
![Page 33: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/33.jpg)
popen()
$pipe = popen(‘ls -l’, ‘r’);fpassthru($pipe);
$mail = popen(‘sendmail -t -i’, ‘w’);fwrite($mail, ‘Subject: hello...’);
![Page 34: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/34.jpg)
proc_open()
• More powerful than popen()
• Cwd
• Environment
• Multiple pipes
• Files
• Suppress GPF dialog (Win32)
• pty
![Page 35: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/35.jpg)
proc_open()
$p = proc_open( ‘--command--fd 0 --status-fd 1’, array( 0 => array(‘pipe’, ‘r’), array( 1 => array(‘pipe’, ‘w’), array( 2 => array(‘pipe’, ‘w’), $pipes, # will hold the pipe handles ‘/’, # child cwd will be / array( # set the environment ‘LOGNAME’ => ‘wez’, ‘HOME’ => ‘/home/wez/’), array(‘suppress_errors’ => 1));
![Page 36: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/36.jpg)
proc_open()
fwrite($pipes[0], ‘some gpg command’);do { $r = array($pipes[1], $pipes[2]); if (stream_select($r, $w = null, $e = null, 30)) { foreach ($r as $p) { $data = fread($p, 8192); $prefix = $p == $pipes[1] ? ‘out’ : ‘err’; echo “$prefix: $data\n”; } }} while (true);
![Page 37: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/37.jpg)
Transports and Wrappers
• Three primitives in PHP Streams:
• Streams themselves (“objects”)
• Transports (“classes”)
• Wrappers (“glue”)
![Page 38: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/38.jpg)
Transports
• Are streams that implement the internal transports API
• fsockopen(): tcp://, udp://, ssl://
• send/receive the data you send/receive
![Page 39: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/39.jpg)
Wrapper
• Glue code that acts as a factory for speaking a protocol
• fopen(): http://, ftp://
• Work happens, and you are handed back a stream
![Page 40: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/40.jpg)
User-defined streams
PHP allows you to create your own stream implementations in PHP
It’s actually a hybrid wrapper/stream
class mystream { # methods go here}
stream_wrapper_register(‘myFile’, ‘mystream’);
![Page 41: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/41.jpg)
User-defined streams
class mystream { var $fp; function stream_open($path, $mode, $options, &$opened_path) { $url = urldecode(substr($path, 9)); $this->fp = fopen($url, $mode); $opened_path = $path; return $this->fp; }}
![Page 42: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/42.jpg)
User-defined streams
... function stream_close() { $this->fp = null; return true; } function stream_read($count) { return fread($this->fp, $count); } function stream_write($data) { return fwrite($this->fp, $data); }...
![Page 43: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/43.jpg)
User-defined streams
... function stream_tell() { return ftell($this->fp); } function stream_eof() { return feof($this->fp); } function stream_seek($offset, $whence) { return fseek($this->fp, $offset, $whence) == 0 ? true : false; }...
![Page 44: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/44.jpg)
User-defined streams
... function stream_flush() { return fflush($this->fp); } function stream_stat() { return fstat($this->fp); } function stream_lock($action) { return flock($this->fp, $action); }...
![Page 45: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/45.jpg)
User-defined streams
... function unlink($path); function rename($old, $new); function mkdir($path, $mode, $opts); function rmdir($path, $opts); function url_stat($path, $flags); function dir_opendir($path, $opts); function dir_readdir(); function dir_rewinddir(); function dir_closedir();...
![Page 46: PHP Streams: Lucky Dip](https://reader033.fdocuments.net/reader033/viewer/2022052909/559868e31a28ab95738b46b5/html5/thumbnails/46.jpg)
Questions?
• My blog: http://netevil.org
• These slides on my blog and on slideshare.net