2009-07-24 4 views
1

Я получаю это странное поведение при наборе веб-сайта с использованием сокета. Строка, возвращаемая из функции 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; 
} 

Печать $ Выход:

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> 

как у других тд-тегов.

Чтобы устранить эту проблему, я заменил гнезда на завиток.

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 исправляет проблему, я хотел бы понять, что здесь происходит. Каково происхождение этой «дополнительной информации»? Из червоточины или что-то в этом роде?

У вас есть мысли?

Спасибо!

ответ

5

сервера вы получаете содержание от передачи данных в режиме фрагментированного (вы можете проверить это, потому что этот заголовок:

Transfer-encoding: chunked 

).

Эта кодировка с распределением каналов работает следующим образом: сервер отправляет шестнадцатеричное число (в символах ascii), представляющее длину следующего фрагмента. Затем он отправляет CRLF (\ r \ n), затем кусок, затем снова CRLF, а затем он запускается снова и снова. Пример:

10 
1234567890abcdef 
0C 
qwertyuiopas 

CURL обрабатывает это, но вы читаете сырые данные сокета, так что появляется в содержании вы ВОССТАНОВЛЕНИЕ.

Таким образом, дополнительный «f43», который вы заметили, которого не было в исходном HTML, на самом деле является длиной следующего фрагмента (3907 байт).

В любом случае, рекомендуется использовать CURL или другую библиотеку HTTP, поскольку реализация протокола со всеми его утилит (например, chunked transfer-encoding в HMTL) - это большая работа, более чем в два раза больше работы по внедрению базовый обработчик протокола, который будет работать только в одном базовом случае.

+0

Чтобы усложнить его, наше недавнее обновление PHP (5.2.9, IIRC) ввело проблему, в которой fpassthru() больше не обрабатывает фрагментированные данные - он начал передавать длины в браузер. Мне пришлось отказаться от fpassthru() и отрешиться от ответа, прежде чем повторять каждый фрагмент. – grantwparks

Смежные вопросы