Глава 19. Эффективная работа в РНР при сетевом соединении с Web-сервером
Данную главу можно было бы назвать «Корректная работа в РНР». Не достаточно знать сами принципы программирования для эффективного процесса написанного вами приложения на РНР, необходимо также учитывать все погрешности, т. е. возможные нюансы выполнения нашего скрипта, а в частности взаимодействия «клиент—сервер». Ведь неизвестно, как именно будет выполнять пользо ватель наш скрипт на сервере. Нет гарантии, что он же не прервет его в процессе передачи данных серверу и выполнения. Следует сделать так, чтобы работа скрипта не проделывалась впустую в случае разрыва соединения или же остановки полнения загрузки данных в браузер пользователя. Это и будет рассмотрено нами в данной главе.
Представьте себе ситуацию, когда ваш скрипт обрабатывает сложный.запрос, что-то читает из базы, пишет в файл, изменяет данные и т. д., а во время этого процесса клиент нажал кнопку «Стоп» и разорвал соединение. Работа вашей программы будет прервана в самый неожиданный момент, и обработка не будет завершена. Но частично-то работа проделана. Необходимо как-то вернуть назад внесенные изменения. Для этого в РНР встроен механизм контроля за соединением. Вы можете подготовить функцию аварийной остановки с помощью register_shutdown_function(). Данная функция вызывается интерпретатором РНР при завершении работы скрипта. Сетевое соединение в РНР с Web-сервером может иметь один из следующих статусов:
0 - NORMAL,
1 - ABORTED,
2 - TIMEOUT.
Когда РНР работает нормально, статус соединений будет NORMAL. Когда клиент прерывает соединение, устанавливается флаг ABORT. Если для выполнения скрипта не хватило времени, то будет установлен флаг TIMEOUT. Обратите внимание на функцию set_time_limit(). Она позволяет ограничить максимальное время выполнения. Ее синтаксис:
void set_time_limit(int seconds)
Функция распространяется на 3 и 4 версии РНР. Функция set_time_limit() позволяет выполнять скрипт на заданное вами время. Если время, заданное на выполнение сценария, достигнуто, то наш скрипт возвратит фатальную ошибку. Предел установления — 30 секунд (установлен по умолчанию в файле конфигурации), но при желании вы можете его изменить. Это изменение производится в файле конфигурации. Строка max_execution_time отвечает за время установления. Когда вы устанавливаете секунды на нуль, никакой предел на выполнение скрипта не наложен. Обратите внимание, чем может быть полезна данная функция. Прежде всего она может позволить нам в случае какой-либо проблемы разрыва программы просто прекратить ее выполнение из-за истечения установленного времени.
В случае вызова функции set_time_limit() автоматически происходит перезапуск счетчика паузы с нуля. Например, если время, установленное по умолчанию, равно 30 секундам, выполнение самого скрипта длится 20 секунд, а время, установленное нами в функции set_time_limit(), равно 15:
то время выполнения нашего скрипта будет равно 35 секундам.
ВНИМАНИЕ
Функция set_time_limit() неэффективна, когда РНР выполняется в режиме safe mode (безопасном режиме). Чтобы она работала корректно, необходимо отключить режим safe mode или изменить предел времени в файле конфигурации.
Вы можете указать интерпретатору, будет или нет ваш скрипт прерван при разрыве соединения. Этот вариант можно выбрать функцией ignore_user_abort(). Другой вариант — это создание функции аварийного завершения при помощи функций connection_aborted();, connection_timeout() и connection_status(). Если вы использовали ignore_user_abort(), то функция аварийного завершения может получить 2 статуса: ABORT, если прервали соединение, и TIMEOUT, если при этом скрипт выполнялся слишком долго.
ВНИМАНИЕ
Оба статуса — и ABORTED и TIMEOUT могут быть активными в одно и то же время. Это возможно в случае, когда вы заставляете РНР игнорировать аварийное завершение, т. е. прекращение операции обращения к ресурсу пользователя. В эти моменты РНР еще будет обращать внимание на то, что пользователь, возможно, прервал соединение, но сам процесс выполнения будет продлен.
Как известно, для сервера самый страшный враг — это сам пользователь. А если таких много на одном сервере? И обязательно найдется тот, кто начнет либо искать спрятанную информацию, либо просто пакостить. В РНР можно ограничить возможность пользовательского скрипта, чтобы предотвратить утечку чужих данных. Провайдеры обычно разрешают пользователям выполнять скрипты в безопасном режиме. Сильно это ограничение не сковывает, но помнить об этом надо.
ВНИМАНИЕ
Все описанное в этой главе распространяется на версию 3.0.7 и старше.
Заключение
Данная глава описала некорректный разрыв соединения, а также способы эффективной нейтрализации последствий.