Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Как работает Keep-Alive?

14K
30 июня 2009 года
Snk
54 / / 22.03.2007
Форум перерыл ничего не нашел... Мне надо всего 1 раз подключиться и отправлять заголовки? Пишу:
Код:
<?
$r  = "GET http://site.com/index.php HTTP/1.1\r\n";
$r .= "Accept: */*\r\n";
$r .= "Accept-Language: ru\r\n";
$r .= "User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; WebMoney Advisor; Pivim Multibar; .NET CLR 2.0.50727; yie8)\r\n";
$r .= "Accept-Encoding: gzip, deflate\r\n";
$r .= "Connection: Keep-Alive\r\n";
$r .= "Host: site.com\r\n";
$r .= "\r\n";

$fp = fsockopen("ip",80,$errno,$errstr,30);

 if ($fp) {

     fputs($fp,$r);

     $bd = "";
     $hed = "";

     while (($fr = fgets($fp)) != "\r\n") $hed .= $fr;

     while (!feof($fp)) {

         $bd .= fread($fp,4096);

         if (substr($bd, -9)=="\r\n\r\n0\r\n\r\n") {

            exit;

         }

    }

    $r  = "GET http://site.com/img.gif HTTP/1.1\r\n";
    $r .= "Accept: */*\r\n";
    $r .= "Accept-Language: ru\r\n";
    $r .= "Referer: http://site.com/index.php\r\n";
    $r .= "User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; WebMoney Advisor; Pivim Multibar; .NET CLR 2.0.50727; yie8)\r\n";
    $r .= "Accept-Encoding: gzip, deflate\r\n";
    $r .= "Connection: Keep-Alive\r\n";
    $r .= "Host: site.com\r\n";
    $r .= "\r\n";

    fputs($fp,$r);

    while (($fr = fgets($fp)) != "\r\n") $hed .= $fr;

    while (!feof($fp)) {

       $bd .= fread($fp,4096);

       if (substr($bd, -9)=="\r\n\r\n0\r\n\r\n") {

          exit;

       }

    }
 
    echo $hed;

 }

fclose($fp);


Нет ответа от сервера... Maximum execution time of 30 seconds exceeded... Если закрываю и открываю заново, тогда все работает.. Пробовал добавлять "Keep-Alive: timeout=5; max=100\r\n" не помогло. Как быть?
5.3K
30 июня 2009 года
Somebody
185 / / 24.12.2006
Некоторые серверы могут закрывать соединение несмотря на keep-alive. Или этот точно нормально работает с keep-alive?
366
30 июня 2009 года
int
668 / / 30.03.2005
А curl нельзя использовать? Он проще.
14K
30 июня 2009 года
Snk
54 / / 22.03.2007
Этот точно работает т.к. если посылать один запрос приходит ответ с "Keep-Alive: timeout=5, max=100 Connection: Keep-Alive".
14K
30 июня 2009 года
Snk
54 / / 22.03.2007
Цитата: int
А curl нельзя использовать? Он проще.


можно но не хочется...

5.3K
30 июня 2009 года
Somebody
185 / / 24.12.2006
[phpdoc]feof[/phpdoc]
Цитата:

Warning
If a connection opened by fsockopen() wasn't closed by the server, feof() will wait until a timeout has been reached to return TRUE.


Тогда при чтении первого ответа всё виснет.

14K
30 июня 2009 года
Snk
54 / / 22.03.2007
Ну так по моему при keep-alive сервер в конце тела возвращает "\r\n\r\n0\r\n\r\n". У меня на это exit. Виснуть не должно!
14K
30 июня 2009 года
Snk
54 / / 22.03.2007
Тем более если посылаю один запрос, сервер также не закрывает соединение и ничего не виснет, так что это тут не причем...
14K
30 июня 2009 года
Snk
54 / / 22.03.2007
Перепробовал pfsockopen, socket_set_blocking + stream_set_timeout... неужели через fsock нельзя работать с keep-alive?
5.3K
01 июля 2009 года
Somebody
185 / / 24.12.2006
Цитата: Snk
Ну так по моему при keep-alive сервер в конце тела возвращает "\r\n\r\n0\r\n\r\n". У меня на это exit. Виснуть не должно!


Кто сказал? Если Transfer-Encoding: chunked, то будет:
\r\n потом 0, потом (теоретически может быть) точка с запятой, фигня после неё и так далее (см. в Google), а может и этого не быть, так что или надо подробно разбираться и парсить http, или посмотреть, как отвечает именно этот сервер и надеяться, что так будет всегда, или не fsock. В любом случае вручную отправить эти заголовки и посмотреть ответ не помешает.

52K
08 сентября 2009 года
vital789
4 / / 08.09.2009
Да действительно инфо по этому вопросу в инете маловато. Но достаточно чтоб работать, хотя на сколько корректно?

1) Нужно учитывать заголовки полученые в режиме Keep-Alive.
Если прислали Connection: Close. Значит сервер скорее всего не поддерживает этот режим или что-то не правильно. Может быть вместо Алива вы послали Close. Или со временем проблема. Лучше слать заголовок Keep-Alive: 300 или сколько угодно вам секунд ожидания от вас "весточки".
После первого запроса, по правилам Алива сервер должен присылать Content-Length: 3232 (кол. байт кода, они нам).
Соответственно столько и считываем данных с сокета, по другому можно определить конец, но не всегода удобно и не без подводных камней. Опять же зависит от заголовков.
После точного считывания проверка сокета на !feof($fp), должно корректно выкочить из цикла, если есть таковой. А потом опять без закрытия шлем запросы в этот же дескриптор и опять читаем. Вот он Alive!

2) Если вы слали заголовок, что не плохо бы сжимать данные - Accept-Encoding: gzip, deflate (непременно лучше слать!!!)
(для оперы - deflate, gzip, x-gzip, identity, *;q=0)
Тогда вам прийдет ЗИП с большой вероятностью и заголовок с указанием, что данные сжаты gzip. Если вы все делайте через fsockopen и т.п. вам не обойтись без расколачивания и расзиповки:
Transfer-Encoding: chunked (если пришлют это, то надо закалачивать), и соотв. проверить пришло ли это:
Content-Encoding: gzip
Тогда надо еще и расзиповывать.

3) И так, если есть заголовки:
Transfer-Encoding: chunked
Content-Encoding: gzip
Надо расскодировать и расзиповывать.
Если один из этих, тогда только одно действие.
Если ничего, значит ничего.

Данные chunked - в самом начале 3-и байта hex размера и превод стоки, за тем следует данные. Если Данные зазипованы, то первый фрагмент надо пропустить, т.к. он должен быть 10 байт, как я понимаю эти данные не нужны вообще, как и концовка, которая может состоять из 8-и байт. Я лично пропускаю размер данных которые меньше 11 байт, это не правильно, но логически и не должно привести к ошибке.

Еще раз, мы рассматриваем данные в chunked и в зипе:
Оболочка chunked, вернее блоки chunked, каждый блок начинается с размера данных в нем и перевод стоки. Потом сначала 10 байт резерва Гзипа, его пропускаем, потом опять перевод стоки \r\n и читаем 3-и 16-иричных числа (которые переводим в десятичку и указываем в функцию), если код 20 то пустота. Затем \r\n а далее полезные данные, их теперь надо расзиповать gzinflate($str,$len), и так каждый блок.
52K
10 сентября 2009 года
vital789
4 / / 08.09.2009
Уточнение,

Сначала надо склеить если chunked заголовок прислан, а потом всю строку расзиповывать, первые 10 байт пропускаем:

$h - массив заголовков.
$d - принятные вэб данные.
На выходе нормальный результат.

Код:
<?php
function decode_gzip($h,$d,$rn="\r\n"){
if (isset($h['Transfer-Encoding'])){
 $lrn = strlen($rn);
 $str = '';
 $ofs=0;
 do{
    $p = strpos($d,$rn,$ofs);
    $len = hexdec(substr($d,$ofs,$p-$ofs));
    $str .= substr($d,$p+$lrn,$len);
    $ofs = $p+$lrn*2+$len;
 }while ($d[$ofs]!=='0');
 $d=$str;
}
if (isset($h['Content-Encoding'])) $d = gzinflate(substr($d,10));
return $d;
}
?>
52K
29 октября 2009 года
vital789
4 / / 08.09.2009
Доработка функции.

Данные могут быть повреждены или еще какие-то неожиданости.
Так же в функции gzinflate есть баг который убран только в самых современных сборках.

Код:
<?php

function decode_gzip($h,$d,$rn="\r\n"){
if (isset($h['Transfer-Encoding'])){
 $lrn = strlen($rn);
 do{
    @$p = strpos($d,$rn,$ofs);
    if($p===false){$str=''; break;}
    $len = hexdec(substr($d,$ofs,$p-$ofs));
    $str .= substr($d,$p+$lrn,$len);
    $ofs = $p+$lrn*2+$len;
 }while ($d[$ofs]!=='0');
 $d=$str;
}
//$slupd = unpack('L',substr($d,-4));
if (isset($h['Content-Encoding']))
{
    static $lim_mem;
    if(!$lim_mem) $lim_mem = ini_get('memory_limit')<<18;
    @$d = gzinflate(substr($d,10),$lim_mem);
}
return $d;
}

?>
52K
11 апреля 2012 года
vital789
4 / / 08.09.2009
Вот апдейт из последних, с ним перелопачено куча в т.ч. и с проксями, вроде сбоев не замечено.

Код:
function decode_gzip($h,$d,$rn="\r\n"){
if (isset($h['Transfer-Encoding:'])){
 $lrn = strlen($rn);
 $ofs=0; $str='';
 do{
    @$p = strpos($d,$rn,$ofs);
    if($p===false){$str=''; break;}
    $len = hexdec(substr($d,$ofs,$p-$ofs));
    $str .= substr($d,$p+$lrn,$len);
    $ofs = $p+$lrn*2+$len;
 }while ($d[$ofs]!=='0');
 $d=$str;
}
if (strlen($d)&&isset($h['Content-Encoding:']))
{
 if($h['Content-Encoding:']==='gzip'){
    static $lim_mem;
    if(!$lim_mem) $lim_mem = ini_get('memory_limit')<<20;
    $slupd = unpack('L',substr($d,-4));
    @$t = ($slupd[1]<$lim_mem)?gzinflate(substr($d,10),$slupd[1]):'';
    if(strlen($t)) return $t;
 }
 @$d=gzinflate($d);
}
return $d;
}
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог