2013-04-13 4 views
3

Я прочитал и глубоко понимал их: http://www.php.net/manual/en/features.connection-handling.php http://www.php.net/manual/en/function.register-shutdown-function.phpPHP не обнаруживает подключение прерывания на всех

Однако я испытал как PHP 5.1.6 и 5.3 и вещи не работают, как описано здесь. Я наблюдаю за этим:

  • connection_status() всегда возвращает true, даже после того, как клиент закрыл соединение.
  • Выполнение скрипта продолжается после того, как клиент закрыл соединение, хотя ignore_user_abort равен 0
  • Функция, зарегистрированная с register_shutdown_function(), не запускается до тех пор, пока сценарий не достигнет конца. Сценарий НЕ прерывается (и, следовательно, функция не вызывается), когда клиент прерывает соединение.

Так что в основном PHP просто не обнаруживает отключение клиента во ВСЕХ.

Обратите внимание, что это НЕ так, как если ignore_user_abort был установлен в 1: если это так, то connection_status() вернет 1, хотя скрипт будет продолжать работать, и функция выключения не будет вызываться до конца. Это не относится к делу.

ini_get ("ignore_user_abort") возвращает 0, как и ожидалось.

Это ошибка в PHP, или это может быть связано с некоторыми настройками Apache?

Как заставить PHP работать, как описано в вышеупомянутой документации?

тест сценарий:

<?php 

function myShutdown() { 
    error_log("myShutdown ".connection_status()." ".ini_get("ignore_user_abort")); 
} 

register_shutdown_function(myShutdown); 

echo "Hi!"; 
error_log(" *** test/test *** "); 
for ($i=0; $i<10; $i++) { 
    sleep(1); 
    error_log("."); 
    echo "."; 
} 
?> 

Шаги для воспроизведения: - посетить URL сценария - прервать соединение на стороне клиента до истечения 10 секунд прошло (например, нажмите кнопку остановки в браузере)

Ожидаемое/Желаемая поведение: бревна должны показывать менее 10 точек, а в конце «myShutdown 1 0» (если вы смотрите журнал в режиме реального времени, myShutDown должен появиться сразу же, когда клиент отключается)

Наблюдаемое/текущее поведение: Журналы всегда показывают ровно 10 точек, а в конце «myShutdown 0 0» (если вы смотрите его в режиме реального времени, оно продолжается 10 секунд независимо от того, когда клиент отключается).

+1

Почему вы используете версию 'PHP' больше не поддерживаются? – Baba

+0

Вы используете php как модуль apache? – hek2mgl

+0

@ hek2mgl yes, как модуль apache – matteo

ответ

5

Во-первых, я также не смог заставить его работать, используя базовую установку LUB для Ubuntu 12.04 (php5.3). Но у меня есть информация и надеюсь, что это будет полезно. Любые комментарии или изменения оцениваются! :)


Я вижу две проблемы с вашим кодом. Первая - синтаксическая ошибка. При вызове register_shutdown_function() вам не хватает одиночных кавычек около myShutdown. Измените строку на:

register_shutdown_function('myShutdown'); 

Вторая проблема, которую я вижу, это не хватает flush() вызова после echo с.В документации указано:

PHP не обнаружит, что пользователь прервал соединение до тех пор, пока не будет предпринята попытка отправить информацию клиенту. Простое использование инструкции echo не гарантирует отправку информации, см. Flush().

Но даже flush() в любом случае не поможет. Из документации flush():

заподлицо() не может быть в состоянии перекрыть схему буферизации вашего веба-сервер, и это не имеет никакого эффекта на любой сторону клиента буферизации в браузере. Он также не влияет на механизм буферизации вывода пользовательского пространства PHP. Это означает, что вам придется вызывать оба ob_flush() и flush(), чтобы очистить выходные выходные буферы, если вы их используете.

Несколько серверов, особенно на Win32, все равно будут буферизовать вывод из вашего скрипта до тех пор, пока он не завершится до передачи результатов в браузер.

Серверные модули для Apache, такие как mod_gzip, могут выполнять собственную буферизацию, что приведет к тому, что flush() не приведет к немедленному отправке данных клиенту.

Даже браузер может буферировать его ввод перед его отображением. Например, Netscape загружает текст до тех пор, пока не получит конец строки или начало тега, и он не будет отображать таблицы до тех пор, пока не будет замечен тег самой внешней таблицы.

Некоторые версии Microsoft Internet Explorer начнут отображать страницу только после того, как они получили 256 байтов вывода, поэтому вам может потребоваться отправить лишние пробелы перед тем, как очистить, чтобы эти браузеры отображали страницу.

В комментариях этой странице есть совет, чтобы установить несколько заголовков и Apache конфиги:

apache_setenv('no-gzip', 1); 
ini_set('zlib.output_compression', 0); 
ini_set('implicit_flush', 1); 

Однако, даже это не работает для меня. Я исследовал это с помощью wireharek, хотя веб-сервер отправляет контент («Привет») после 0,0037 секунд, веб-браузер буферизует страницу.

+0

Вы должны удалить часть пропущенных одиночных кавычек. rehister_shutdown_function() принимает вызываемый, а функция является вызываемой. В противном случае я бы получил ошибку btw, что не так. – matteo

+2

Обратите внимание, что вы получите: 'Примечание: использование неопределенной константы myShutdown - предполагаемое« myShutdown »в ...'. Вы должны увеличить уровень 'error_reporting' – hek2mgl

+0

Я вижу! буферизация вывода должна быть проблемой. Я предполагаю, что apache буферизует его, даже если gzipping отключен и независимо от скрытого флеша PHP, вероятно, поэтому даже попытка вашей попытки обхода не работает. – matteo

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

  • Нет связанных вопросов^_^