Php 来自带套接字fgets的feof()的假eof

Php 来自带套接字fgets的feof()的假eof,php,fgets,fsockopen,feof,Php,Fgets,Fsockopen,Feof,我继承了一段代码,它使用下面的fetchURL()函数从url获取数据。我刚刚注意到,在检索整页数据之前,feof()通常会返回true。我尝试了一些测试,并使用file\u get\u contents()的CURL每次都检索完整的页面 错误是间歇性的。在9次呼叫中,有时7次成功完成,有时仅4次。9个请求中的特定4个(它们是get请求,只有一个不断变化的查询字符串)始终成功完成。我尝试过颠倒请求的顺序,相同的4个查询字符串始终成功,而其余的查询字符串有时有效,有时无效。 因此,“似乎”返回的数

我继承了一段代码,它使用下面的
fetchURL()
函数从url获取数据。我刚刚注意到,在检索整页数据之前,
feof()
通常会返回true。我尝试了一些测试,并使用
file\u get\u contents()
CURL
每次都检索完整的页面

错误是间歇性的。在9次呼叫中,有时7次成功完成,有时仅4次。9个请求中的特定4个(它们是get请求,只有一个不断变化的查询字符串)始终成功完成。我尝试过颠倒请求的顺序,相同的4个查询字符串始终成功,而其余的查询字符串有时有效,有时无效。
因此,“似乎”返回的数据可能与问题有关,但正是间歇性让我困惑。在每种情况下返回的数据总是相同的(如中所示,每次我使用
?SearchString=8502806
的查询字符串进行调用时,返回的页面包含相同的数据),但有时整页由
fgets/feof
传递,有时则不是

有没有人对造成这种情况的原因有什么建议?关于这个主题,我看到的大多数其他帖子都是关于相反的问题,
feof()
没有返回true

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));
}

对我来说,这听起来像是个超时问题。请参阅PHP手册。

我发现该代码有很多地方出错

  • 不要在插座上使用feof。它将一直挂起,直到服务器关闭套接字,这不一定在收到页面后立即发生
  • feof
    可能返回
    true
    (套接字已关闭),而PHP的缓冲区中仍有一些数据
  • 区分头和体的代码似乎依赖于PHP正确地完成它的工作,这通常是个坏主意
    fgets
    不一定要读取一行,它也可以只返回一个字节(
    \r
    ,那么下次调用时您可能会得到
    \n
  • 您没有正确编码路径值

为什么不将代码转换为使用cURL或file_get_contents?

feof
放在套接字上通常(总是?)是个坏主意,因为它会等待服务器实际关闭套接字后再继续。至少您应该发送
连接:close
标题,但我还是郑重建议您完全重写这段代码,因为这太糟糕了(无意冒犯)。我正计划转换为CURL,但我想知道是什么导致了我看到的问题。因此,问题就来了。超时就像异常一样,如果出现问题,你应该用它们来捕捉错误,但不能用于正常使用。@TomvanderWoerdt从Internet获取数据时,超时是不可避免的。这是对不可预测行为的合理解释,不是吗?是的,超时是不可避免的,但从问题来看,他没有遇到任何超时。绝对不是所有请求的20%。@TomvanderWoerdt我同意这是一段糟糕的代码,但由于正在更改的数据是一个查询字符串,因此远程主机在某些查询上花费的时间比其他查询长是完全合理的。我不再多说了。我正计划转换为CURL,但我想知道是什么导致了我所看到的问题。这就是问题所在。