Огонь и забудь в PHP - PullRequest
       19

Огонь и забудь в PHP

0 голосов
/ 01 августа 2011

Окончательное обновление

Похоже, я сделал очень простую ошибку. Поскольку у меня уже есть реализация потока, я не могу начать чтение из потока: D


Я пытаюсь достичь огненно-забытого подобного функционала в PHP.

с php.net

<?php
ignore_user_abort(true);
header("Content-Length: 4");
header("Connection: Close");
echo "abcd";
flush();

sleep(5);    
echo "Text user should not see"; // because it should have terminated
?>

Это работает, если я открываю скрипт в браузере. (показывает «abcd»). Но если я открою его с помощью file_get_contents или какой-нибудь библиотеки stream , он будет ждать около 5 секунд и покажет второй текст.

Я использую PHP 5.2.11 / Apache 2.0


Обновление

Мне кажется, что я не совсем понимаю, чего я пытаюсь достичь.

Я не хочу скрывать вывод, используя выходные буферы (это глупо). Я хочу, чтобы клиент завершил свою работу до того, как сервер запустит, возможно, длительный процесс (sleep(5)), и я не хочу, чтобы клиент ждал его (это то, что означает «забей и забудь», сортируйте). Использование выходных буферов является лишь побочным эффектом. Я исправил пример кода без использования выходных буферов.

Что я не понимаю, так это: почему этот скрипт ведет себя по-разному при доступе к нему из браузера и при извлечении его в PHP с file_get_contents("http://dev/test.php") или некоторой stream библиотекой? Что я видел в тестировании, так это то, что, например, stream_get_contents будет на самом деле блокироваться на 5 секунд, прежде чем он вообще выдаст какие-либо выходные данные, что является полной противоположностью того, что я хочу.

Update2

Еще несколько результатов:

  • Браузер как-то реагирует на flush(). Я не могу понять, как повторить это поведение с streams в PHP, мои потоки продолжают блокировать.
  • Я попробовал fread и обнаружил, что он ведет себя подобно stream_get_contents.
  • Указание maxlength не имеет никакого эффекта, оно будет блокироваться в течение ~ 5 секунд.
  • Изменение режима блокировки не имеет никакого эффекта (кроме генерации множества вызовов to stream_get_contents()). Он будет ждать ~ 5 секунд, прежде чем что-либо вернуть.
  • stream_set_read_buffer не имеет никакого эффекта (проверено на сервере PHP 5.3.5)

Ответы [ 3 ]

0 голосов
/ 02 августа 2011

Как получить доступ к сценарию с помощью file_get_contents? Как вы получаете к нему доступ через браузер? Если вы обращаетесь к сценарию без "http://",, конечно, он никогда не будет выполнен. Используйте тот же URL, что и в браузере.

Edit:

Браузер отобразит страницу даже до закрытия соединения. Даже если вы сбросите, я не думаю, что соединение закрыто. Вы можете запустить Wireshark и проверить. stream_get_contents и file_get_contents будут блокироваться, пока у них не будет всех выходных данных. Даже если вы покраснели, они не могут быть уверены, что контента больше нет. Поскольку заголовок длины содержимого, похоже, не возвращает {file, stream} _get_contents ранее, вам, вероятно, нужно реализовать собственную буферизацию, аля. fopen, читать, fclose.

0 голосов
/ 02 августа 2011

Похоже, я сделал очень простую ошибку.Поскольку у меня уже есть реализация потока, я не могу начать чтение из потока: D

0 голосов
/ 01 августа 2011

Вторая часть текста появляется, потому что вы прекращаете буферизацию вывода с помощью ob_end_flush() и ob_end_clean(). Когда это происходит, PHP выводит контент как обычно. Попробуйте что-то вроде следующего:

<?php

ob_start(); // turn on output buffering
print "Text the user will see.";
ob_flush(); // send above output to the user and keep output buffering on

print "Text the user will never see";

ob_end_clean(); // empty the buffer and turn off output buffering. your script should end here.

?>

Важно, чтобы ob_end_clean() появился в конце скрипта. Он очищает буфер и не отправляет его содержимое пользователю, сохраняя все после ob_flush() скрытым.

...