使用套接字时的奇怪行为

时间:2009-07-24 17:40:27

标签: php

使用套接字获取网站时,我遇到了这种奇怪的行为。从下面的get_content()函数返回的字符串包含一些原始网站上没有的“额外信息”。

function get_content($a, $b, $c = "00")
{
    $request  = "arg01="  . $a;
    $request .= "&arg02="  . $b;
    $request .= "&arg03="  . $c;

    $host = "www.site.com";
    $script = "/page.php";
    $method = "POST";

    $request_length = strlen($request);

    $header = "$method $script HTTP/1.1\r\n";
    $header .= "Host: $host\r\n";
    $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $header .= "Content-Length: $request_length\r\n";
    $header .= "Connection: close\r\n\r\n";
    $header .= "$request\r\n";

    $socket = @fsockopen($host, 80, $errno, $errstr);
    if ($socket) {
        fputs($socket, $header);
            while(!feof($socket)) {
                $output .= fgets($socket);
            }
        fclose($socket);
    }

    return $output;
}

打印$ output:

HTTP/1.1 200 OK
Date: Fri, 24 Jul 2009 15:20:38 GMT
Server: Apache/2.2.8 (Unix) PHP/4.4.8
X-Powered-By: PHP/4.4.8
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html

1f61
<html>
<head>
    <title>

    (...) html here (...)
            <td align='right'><font size='-1'>   18,65</font></td>
    (...) html here (...)
            <td align='right'><font size='-1'>   24,10</font></td>
    (...) html here (...)
            <td align='right'><font size='-1'>   18,40</font></td>
    (...) html here (...)
            <td align='right'><font size='-1'>   24,10</font></td>
    (...) html here (...)
            <td align='right'><font size='-1'>   24,10</font></td>
    (...) html here (...)
            <td align='right'><font size='-1'>   18,65</font></td>
    (...) html here (...)
            <td align='right'><font size='-1'>
f43
   24,10</font></td>
    (...) html here (...)
            <td align='right'><font size='-1'>   18,65</font></td>
    (...) html here (...)
            <td align='right'><font size='-1'>   18,65</font></td>
    (...) html here (...)
            <td align='right'><font size='-1'>   24,10</font></td>
    (...) html here (...)
            <td align='right'><font size='-1'>   18,40</font></td>

    (...) html here (...)
   </body>
</html>

0

请注意以下块:

            <td align='right'><font size='-1'>
f43
   24,10</font></td>

它不存在于原始HTML上。应该是

            <td align='right'><font size='-1'>   24,10</font></td>

就像其他人的标签一样。

为了解决这个问题,我用curl替换了套接字。

function get_content($a, $b, $c = "00")
{
    $args  = "arg01="  . $a;
    $args .= "&arg02="  . $b;
    $args .= "&arg03="  . $c;

    $host = "http://www.site.com/page.php";

    $ch = curl_init($host);
    curl_setopt($ch, CURLOPT_URL, $host);
    curl_setopt($ch, CURLOPT_POST, count($args));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $args);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_exec($ch);
    $output = curl_multi_getcontent($ch);
    curl_close($ch);

    return $output;
}

尽管CURL解决了这个问题,但我想了解这里发生了什么。这个“额外信息”的起源是什么?从虫洞或类似的东西?

你有什么想法吗?

谢谢!

1 个答案:

答案 0 :(得分:5)

您从中获取内容的服务器以分块模式传输数据(您可以检查这个,因为有这个标题:

Transfer-encoding: chunked

)。

Chunked传输编码以这种方式工作:服务器发送一个十六进制数字(以ascii字符表示),表示下一个块的长度。然后它发送一个CRLF(\ r \ n),然后是块,然后再发送CRLF,然后它重新开始。例如:

10
1234567890abcdef
0C
qwertyuiopas

CURL处理此问题,但您正在读取原始套接字数据,因此它会显示在您要检索的内容中。

因此,您注意到的附加“f43”(原始HTML中没有)实际上是后续块的长度(3907字节)。

无论如何,使用CURL或其他HTTP库是个好主意,因为实现一个包含所有子实用程序的协议(比如HMTL中的分块传输编码)需要做很多工作,比实现基本工作的工作量大两倍多。协议处理程序,仅适用于一个基本案例。