fgets is faster but stream_get_line is more useful in a tcp server scripts.
when fgets reads some bytes from socket, where EOF is reached, it returns bool(false) same as stream_get_line
BUT if remote client drops connection, and server script will try to read some data with function fgets, function will return bool(false), and stream_get_line will return string(0) ""
so you can detect remote client disconnection with stream_get_line, and cannot with fgets
stream_get_line
(PHP 5)
stream_get_line — 指定されたデリミタの位置までのデータを一行分としてストリームから読み込む
説明
string stream_get_line
( resource
$handle
, int $length
[, string $ending
] )指定したハンドルから一行取得します。
読み込みは、length バイト読まれたか、
ending で指定された文字列がストリームに見つかった
か (この文字列は返値に 含まれません)、あるいは
EOF に達したとき、のうち一番最初に遭遇したところで停止します。
この関数は fgets() とほとんど同一ですが、 \n や \r 、\r\n といった一般的な文字列以外を行末を示すデリミタ として指定できる点で、またデリミタ自体を返値に 含まない 点で異なります。
パラメータ
-
handle -
有効なファイルハンドル。
-
length -
ハンドルから読み込むバイト数。
-
ending -
オプションのデリミタ文字列。
返り値
最大 length バイトの、
handle で指定されたリソースから読み込んだデータを返します。
エラーが発生した際には、FALSE を返します。
pk at ritm dot ru
30-Nov-2009 10:30
amoo_miki at yahoo dot com
19-Aug-2008 12:34
If the "ending" is a string, there are cases where the function doesn't return the correct value for the first time it is called. Don't be shocked if you find it returning a string value of upto "length" that includes the "ending". (See bug #44607)
If the "ending" is just a single character, the function would always work correctly. ("\n" is a single character)
Temporarily, until this is fixed, the below function can be used:
<?php
function istream_get_line(&$fp, $length, $end) {
$current = ftell($fp);
$str = fread($fp, $length);
$i = strpos($str, $end);
if ($i === FALSE) {
return $str;
} else {
fseek($fp, $current + $i + strlen($end));
return substr($str, 0, $i);
}
}
?>
Mat Jaggard at Tickets dot com
20-Dec-2007 09:12
I've spent quite a while trying to get stream_get_line to get a chunk encoded html file and to finish correctly at the end so that I can pipeline requests.
This is the function I have come up with.
<?php
function getURLContents($url, $ip, $port, $ssl = false, $closeConnection = false)
{
if ($ssl)
$ssl = 'ssl://';
else
$ssl = '';
$fp = pfsockopen($ssl.$ip, $port, $errno, $errstr, MAX_TIME_TO_START_CONNECTION);
if ($fp)
{
$out = 'GET '.$url." HTTP/1.1\r\n";
$out .= 'Host: '.$ip.':'.$port."\r\n";
if ($closeConnection)
$out .= "Connection: close\r\n";
else
$out .= "Connection: keep-alive\r\n";
$out .= "\r\n";
if (!fwrite($fp, $out))
{
echo 'Problem writing to socket, opening a new connection.';
fclose($fp);
$fp = pfsockopen($ssl.$ip, $port, $errno, $errstr, MAX_TIME_TO_START_CONNECTION);
fwrite($fp, $out);
}
$theData = '';
$notDone = true;
stream_set_blocking($fp, 0);
$startTime = time();
$lastTime = $startTime;
while (!feof($fp) && !$done && (($startTime + MAX_TIME_FOR_THE_RESPONSE) > time()))
{
usleep(100);
$theNewData = stream_get_line($fp, 1024, "\n");
$theData .= $theNewData;
$done = (trim($theNewData) === '0');
}
}
else
{
echo 'ERROR CONNECTING TO '.$ip.':'.$port;
return false;
}
if ($closeConnection)
fclose($fp);
return $theData;
}
?>
dante at lorenso dot com
08-Jun-2006 02:34
My testing has found this function to be dramatically faster than fgets on PHP 5.1.14. The difference is probably due to how buffering is used internally. Compare the following:
<?php
// reads 10,000 lines in 27 seconds
while (!feof($handle)) {
$line = fgets($handle, 1000000);
}
?>
vs.
<?php
// reads 10,000 lines in 0.5 seconds
while (!feof($handle)) {
$line = stream_get_line($handle, 1000000, "\n");
}
?>
18-Apr-2006 04:07
In version 5.0.4 using this funtion and then calling ftell($stream) would give you the position up to but not including the "ending" string.
When I rev'd to PHP version 5.1.2, calling this function then using ftell($stream) would give the position up to AND including the "ending" string
for example, parsing HTTP responses.
The response from apache using curl....
------------------------------------------------------------
HTTP/1.1 200 OK
Date: Tue, 18 Apr 2006 20:54:59 GMT
Server: Apache/1.3.33 (Unix) PHP/5.0.4 mod_ssl/2.8.22 OpenSSL/0.9.7e
X-Powered-By: PHP/5.0.4
Transfer-Encoding: chunked
Content-Type: text/html
<html><body>test</body></html>
-------------------------------------------------------------
The code:
<?php
$headers = stream_get_line($in,4096,"\r\n\r\n");
fseek ($in,ftell($in)+4);
while (!feof($in)){
fputs ($out,stream_get_line($in,4096,''));
}
?>
prior to my 5.0.4 this worked perfectly, trimming the \r\n\r\n section of the HTTP response and seperating the top into the $headers string, and the rest was placed into the file handle $out.
using php 5.1.2, the above code chopps off the first 4 bytes of the HTTP response and puts
l><body>test</body></html>
into $out.
