PHP fsockopen()/ fread()返回搞砸的数据

时间:2009-08-14 19:13:22

标签: php fread fsockopen

我用fsockopen()和fread()读了一些URL,我得到了这样的数据:

      <li
10 
></li>
      <li
9f 
>asd</li>

d  
          <li
92 

这完全搞砸了O_O

-

使用file _ get _ contents()函数时,我得到了这样的数据:

<li></li>
      <li>asd</li>

哪个是对的!那么,HELL错了什么?我试过我的Windows服务器和Linux服务器,两者表现相同。他们甚至没有相同的PHP版本。

-

我的PHP代码是:

$fp = @fsockopen($hostname, 80, $errno, $errstr, 30);
if(!$fp){
    return false;
}else{
    $out = "GET /$path HTTP/1.1\r\n";
    $out .= "Host: $hostname\r\n";
    $out .= "Accept-language: en\r\n";
    $out .= "Connection: Close\r\n\r\n";
    fwrite($fp, $out);

    $data = "";
    while(!feof($fp)){
        $data .= fread($fp, 1024);
    }
    fclose($fp);

感谢任何帮助/提示,​​现在一整天都在想:/

哦,我不能使用fopen()或文件_ get _ contents(),因为我的脚本运行的服务器没有启用fopen包装器&gt; __&lt;

我真的想知道如何解决这个问题,只是为了好奇。我不认为我可以在这台服务器上使用任何额外的库。

3 个答案:

答案 0 :(得分:1)

您可能想要使用cURL.

<?php
// create a new cURL resource
$ch = curl_init();

// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, "http://www.example.com/");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

// grab URL and pass it to the browser
$output = curl_exec($ch);

// close cURL resource, and free up system resources
curl_close($ch);
?>

答案 1 :(得分:1)

关于您的“奇怪数据”问题,这可能是因为您请求数据的服务器正在以分块模式传输它。

在浏览器中调用相同的URL时,您可以查看HTTP标头;其中一个标题可能是这样的:

Transfer-encoding: chunked


引用wikipedia's article on that matter

  

每个非空的块都以   它嵌入的数据的八位字节数   (接着是用十六进制写的大小)   由CRLF(回车和线路   feed)和数据本身。块   然后用CRLF关闭。在一些   实现,白色空间   填充字符(0x20)   chunk-size和CRLF。

     

最后一个块是一行,   简单地由块大小(0)组成,   一些可选的填充空格和   终止CRLF。它不是   随后是任何数据,但可选   可以使用相同的方式发送预告片   语法作为邮件标题。

     

该消息最终由a关闭   最终的CRLF组合。

这看起来很接近你得到的......所以我猜这是问题所在。


据我所知,curl知道如何处理 - 所以,简单的方法是使用curl而不是fsockopen等

使用curl通常是一个更好的想法,使用套接字:它将处理您可能遇到的许多问题;喜欢这个; - )


Anoter的想法,如果你的服务器上没有启用curl,那就是使用一些已经存在的基于fsockopen的库 - 希望它已经为你处理这些事情。

例如,我曾与Snoopy一起工作过几次;也许它已经知道如何处理?
(不确定:您必须自己测试 - 或者查看文档以了解这是否正常)
不过,如果你想自己处理HTTP协议的奥秘......好吧,祝你好运!

答案 2 :(得分:1)

使用fsockopen(),您将获得原始TCP数据,而不是HTTP内容。我假设你也看到了HTTP标题,对吗?如果它采用分块编码,您将获得所有块头。

这是一个已知问题。有人发布了关于如何删除块头的解决方案here