Управление выводом
ob_start();
for ($i=0; $i<2000; $i++){
$echo.=$i."\n";
}
echo strlen($echo).$echo;
header("Content-Type: text/html");
header("Content-Length: ".ob_get_length());
header('Connection: close');
ob_end_flush();
sleep(10);
//Дальнейшее выполнение скрипта
?>
Так вот когда размер выводных данных более 8кб скрипт отрабатывает как должен - отдает контент и продолжает работу через 10 секунд но браузер этого уже не знает. Если размер менее 8 кб, то выдача в браузер идет только после sleep. Что влияет на такое поведение?
[COLOR="Silver"]ЗЫ В чем прикол называть переменные также как встроенные в язык функции и структуры?[/COLOR]
[COLOR="DimGray"]P.S. В таких случаях крайне рекомендую к использованию какой либо снифер. Лично я за Wireshark.[/COLOR]
Наверно не смущает потому что стоит ob_start.
По методу измерения - путем простого подбора, до тех пор пока контент не отдастся сразу, а не будет ждать завершения выполнения скрипта. Можно изменить в цикле значение на 1500 например и контент не отдастся до завершения скрипта.
Для чего: есть скрипт который выполняется довольно долго, ответ клиенту нужно дать быстро, что мол не волнуйтесь все работает, не прерывая выполнения скрипта. Можно пойти и другими путями, но пока более крсивым кажется этот. Если посладть заголовок Location:/ все равно переход произойдет только после выполнения скрипта.
На основе данного примера все работает, смущает посылка лишних килобайтов, но это не критично (хотя интересно почему). Буфер браузера - возможно, но в таком случае у IE и мозилы одинаковый буфер.
Интесно еще одно поведение даже не знаю кого (браузера или сервера). При таком выводе в том же окне (для IE) или новой вкладке (мозила) браузер отказывается выводить любые страницы с данного домена до тех пор пока работает скрипт (а работать он может очень долго), при чем для нового окна (процесса) все работает нормально.
Я правда хз, как это поможет вдруг тебе, но всё же..
Я правда хз, как это поможет вдруг тебе, но всё же..
не совсем понимаю где вызывать flush если я вызываю [COLOR=#0000bb][FONT=Courier New]ob_end_flush[/FONT][/COLOR][COLOR=#007700][FONT=Courier New]();[/FONT]
[/COLOR]
Не проще ли сделать как все белые люди реализуют тот же например прогресс бар? Зачем сношать себе мозг. jQuery в помощь.
Вот как раз там были проблемы, которые почему-то решились только совместным использованием этих обоих flush-функций. Правда, у меня не было ob_start();, т.е. шел сразу вывод в поток.
Вообщем, я сам хз, почему у меня работало тогда только так %) Магия %)
Не проще ли сделать как все белые люди реализуют тот же например прогресс бар? Зачем сношать себе мозг. jQuery в помощь.
В данной ситуации быстрей и красивей решение выше, т.к в противном случае прийдется полностью переписывать скрипт который достался в наследство (не хочется). А про кривой серв и т.д. легко проверить запустив пример выше со слипом минуту к примеру.
Fenyx, что тебе мешает писать код по-человечески?
[highlight=php]
<?php
ob_start();
header("Content-Type: text/html");
header('Connection: close');
$output = "";
for ($i=0; $i<2000; $i++){
$output.=$i."\n";
}
echo strlen($output).$output;
ob_end_flush();
sleep(10);
//Дальнейшее выполнение скрипта
?>
[/highlight]
Fenyx, что тебе мешает писать код по-человечески?
Зачем Content-Length - да затем что бы браузер перестал ждать ответа от сервера. По этой же причине заголовки посылаются ПОСЛЕ формирования контента попавшего в буфер
$echo = '';
ob_start();
for ($i=0; $i < 60; $i++)
{
$echo .= $i."\n";
}
echo strlen($echo).$echo;
header("Content-Type: text/html");
header("Content-Length: ".ob_get_length());
header('Connection: close');
ob_end_flush();
ob_flush();
flush();
sleep(10);
//Дальнейшее выполнение скрипта
?>
Вот как раз там были проблемы, которые почему-то решились только совместным использованием этих обоих flush-функций. Правда, у меня не было ob_start();, т.е. шел сразу вывод в поток.
Вообщем, я сам хз, почему у меня работало тогда только так %) Магия %)
Магию оставь циганкам с вокзала ;)
На пути от скрипта до отрисовки страницы в браузере кроме буферов самого PHP (output_buffering) существует масса других буферов. Это и буфера самого апача (к слову в модуле mod_deflate величина DeflateBufferSize по дефолту как раз равна 8кБ), TCP буфера, буфера браузера и черт-еще-знает-какие-в-каждом-конкретном-случае. Поэтому то, что PHP сбросил свои буферы вовсе не значит, что это сделали другие промежуточные звенья. Я не копал исходники PHP, но сильно подозреваю, что ob_flush() сбрасывает буферы самого PHP, а flush() заставляет выполнить сброс промежуточных буферов (скорее всего через какой то системный вызов).
Кроме того чтение манула повышает ум и сообразительность, ум и сообразительность:
Flushes the write buffers of PHP and whatever backend PHP is using (CGI, a web server, etc). This attempts to push current output all the way to the browser with a few caveats.
flush() may not be able to override the buffering scheme of your web server and it has no effect on any client-side buffering in the browser. It also doesn't affect PHP's userspace output buffering mechanism. This means you will have to call both ob_flush() and flush() to flush the ob output buffers if you are using those.
Several servers, especially on Win32, will still buffer the output from your script until it terminates before transmitting the results to the browser.
Server modules for Apache like mod_gzip may do buffering of their own that will cause flush() to not result in data being sent immediately to the client.