提问人:Captain Payalytic 提问时间:3/30/2013 最后编辑:Abhishek GuptaCaptain Payalytic 更新时间:3/30/2013 访问量:2706
来自 feof() 的 false eof 与套接字 fgets
False eof from feof() with sockets fgets
问:
我继承了一段代码,该代码使用以下函数从 url 中获取数据。我刚刚注意到,在检索整页数据之前,它通常会返回 true。我已经尝试了一些测试,并且每次都使用两者来检索整个页面。fetchURL()
feof()
CURL
file_get_contents()
该错误是间歇性的。在 9 次通话中,有时 7 次会成功完成,有时只有 4 次。9 个中的特定 4 个(它们是仅具有更改查询字符串的获取请求)始终成功完成。我尝试颠倒请求的顺序,相同的 4 个查询字符串仍然总是成功的,而其余的有时有效,有时无效。
因此,“似乎”返回的数据可能与问题有关,但间歇性让我感到困惑。在每种情况下返回的数据始终是相同的(例如,每次我使用返回的页面的查询字符串进行调用时都包含相同的数据),但有时整个页面是由传递的,有时不是。?SearchString=8502806
fgets/feof
有没有人对可能导致这种情况的原因有任何建议?O 看到的关于这个主题的大多数其他帖子都是关于相反的问题,即没有返回真实。feof()
function fetchURL( $url, $ret = 'body' ) {
$url_parsed = parse_url($url);
$host = $url_parsed["host"];
$port = (isset($url_parsed["port"]))?$url_parsed["port"]:'';
if ($port==0)
$port = 80;
$path = $url_parsed["path"];
if ($url_parsed["query"] != "")
$path .= "?".$url_parsed["query"];
$out = "GET $path HTTP/1.0\r\nHost: $host\r\n\r\n";
$fp = fsockopen($host, $port, $errno, $errstr, 30);
fwrite($fp, $out);
$body = false;
$h = '';
$b = '';
while (!feof($fp)) {
$s = fgets($fp, 1024);
if ( $body )
$b .= $s;
else
$h .= $s;
if ( $s == "\r\n" )
$body = true;
}
fclose($fp);
return ($ret == 'body')?$b:(($ret == 'head')?$h:array($h, $b));
}
答:
-1赞
grahamj42
3/30/2013
#1
对我来说,这听起来像是一个超时问题。参见 PHP 手册中的 stream_set_timeout()。
评论
0赞
Tom van der Woerdt
3/30/2013
超时就像异常一样,如果出现问题,您应该使用它们来捕获错误,但不适用于正常使用。
0赞
grahamj42
3/30/2013
从 Internet 获取数据时,@TomvanderWoerdt超时是不可避免的。这是对不可预测的行为的合理解释,不是吗?
0赞
Tom van der Woerdt
3/30/2013
是的,超时是不可避免的,但从问题来看,他没有遇到任何超时。绝对不是所有请求的 20%。
0赞
grahamj42
3/30/2013
@TomvanderWoerdt 我同意这是一段糟糕的代码,但由于正在更改的数据是查询字符串,因此远程主机在某些查询上花费的时间比其他查询更长的时间是完全合理的。我不会再说了。
2赞
Tom van der Woerdt
3/30/2013
#2
我看到该代码有很多问题。
- 永远不要在套接字上使用。它将挂起,直到服务器关闭套接字,这不一定在收到页面后立即发生。
feof
feof
可能会返回(套接字已关闭),而 PHP 的缓冲区中仍有一些数据。true
- 您区分标头和正文的代码似乎依赖于 PHP 正确地完成它的工作,这通常是一个坏主意。 不一定读取一行,它也可以只返回一个字节(,那么下一次调用你可能会得到
fgets
\r
\n
) - 未正确编码路径值
为什么不直接将代码转换为使用 cURL 或 file_get_contents?
评论
0赞
Captain Payalytic
3/30/2013
我打算转换为 CURL,但我想知道是什么原因导致了我所看到的问题。因此问题来了。
评论
feof
在套接字上通常(总是?)是一个坏主意,因为它会等待服务器实际关闭套接字,然后再继续。至少你也应该发送标头,但我强烈建议完全重写这段代码,因为它很糟糕(无意侮辱)。Connection: close