[php, сокет] в чём неверность алгоритма?

356ft85

подскажите, пожалуйста.
Этот алгоритм полчуает содержимое удалённого файла,
но в результате выводится помимо содержимого ещё что-то, неотносящееся к нему,
например, в начале потока появляются три символа
eac, а затем идёт содержимое страницы
 
 <?php
@$fp = fsockopen("forum.local", 80, $errno, $errstr, 10);
    if (!$fp)
     header("HTTP/1.0 404 Not Found");
    else
    {
     $out = "GET / HTTP/1.1\r\n";
     $out .= "Host: 127.0.0.1\r\n";
     $out .= "Connection: Close\r\n\r\n";
     stream_set_timeout($fp, 2);
     fwrite($fp, $out);
     $flag=0;
     while (!feof($fp
     {
     $s=fgets($fp, 1024);
     if ($flag) echo $s; //Пропускаем заголовки до пустой строки
     if ($s=="\r\n" || $s=="\r" || $s=="\n") $flag=1;
     flush;
     }
     fclose($fp);
    }
    
?>

alexkravchuk

Посмотри возвращаемый заголовок http. Возможно, там есть строка
Transfer-Encoding: chunked 

Тогда дело в ней, скорее всего.

artimon

Это длина контента
0xeac = 3756 байт.

artimon

Что б не мучаться замени протокол с 1.1 на 1.0.

alexkravchuk

Это длина контента
0xeac = 3756 байт.
Только чуть хитрее - это длина контента до следующей такой бяки (очередного блока с длиной, то есть)

johnny2000

это точно?
так написано в стандарте HTTP ?
сейчас проверю

356ft85

alexkravchuk

Всё верно... eac - это объём куска с данными, за ним следует заголовок блок с длиной следующего куска, и т.д. Только включается ли длина заголовка в длину следующего куска - не помню, но вроде нет, в любом случае это несложно проверить.

356ft85

стал проверять, но что-то не вяжется:

alexkravchuk

0x0d0A - переход на новую строку
0x10d - это как раз длина пакета, 269 байт. То есть здесь не хватает 4 байт, а точнее - последний блок, где 0 стоит, какой-то неправильный...
А, не туда посмотрел... Пока думаю...

alexkravchuk

А ты случаем в каком-нибудь обычном редакторе этот файл не открывал? Дело в том, что у меня для перевода строки в этом форуме использется просто 0x0a, а не 0x0d0a... Какая-то программа, возможно, что-то скорректировала, или не может ли быть так, что ты в файл некорректно сохранил? Например открыл его как "w", вместо "wb"? Правда php вроде как "wb" всегда открывает...

356ft85

сохранено с точностью до байта вроде. Откуда у тебя такая информация о значении "мусора"
?
если у тебя сервера есать под рукой, можешь запустить скрипт и посмотреть, может он выдаёт другое(?).

artimon

Объясни мне зачем тебе эти мучения с chunk'ами?
Напиши
GET / HTTP/1.0
вместо
GET / HTTP/1.1
и не парься.

356ft85

зачёт и тема закрыта

alexkravchuk

Я посмотрел, что выдаёт конкретно forum.b.gz.ru - вот, у тебя сохранено неправильно, то есть в исходный файл, если ты это делал через fwrite, может и правильно сохранено, но на каком-то этапе - ошибка. Переход на следующую строку в коде страниц форума - без "\r" (то есть без 0x0d). На каком этапе это у тебя появляется - нужно искать.

artimon

И, раз пошла такая пьянка, то чем тебя не устроил
echo file_get_contents('');

kruzer25

А если хочется не просто получить содержимое файла?
Например, написать прокси-сервер на пхп...

kruzer25

Он, может, в файл пишет как-нибудь так:
$str=fgets(...);
fwrite($file,$str."\n");

alexkravchuk

А можно ли как-нибудь в php обойтись без сокетов, но установить свои поля user-agent, referer и другие? Про агент вроде сказано, что только правкой php.ini лечится, а про referer вообще не представляю... Верю, что как-нибудь возможно, но как - не знаю...

viktor_09

Если я правильно понял, надо получить страницу в переменную, при этом отдав нужный юзер-агент и реферер?
Если да, то это можно сделать так:
$ch=curl_init;
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_URL,"forum.local");
curl_setopt($ch,CURLOPT_USERAGENT,"Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");
curl_setopt($ch,CURLOPT_REFERER,"http://forum.b.gz.ru/");
$data=curl_exec($ch);
curl_close($ch);

356ft85

Нет, текст скрипта я привёл, а сохраняю его вывод (echo скачивая его содержимое оперой на диск. Но в любом случае 1.0 решил проблему.
Оставить комментарий
Имя или ник:
Комментарий: