Новая версия психотерапевтического сервера, предназначенного для запуска с помощью демона inetd в режиме wait, будет описана ниже. Соответствующая запись в файле /etc/inetd.conf почти полностью совпадает с первоначальной, за исключением того, что в четвертом поле указана опция wait, а в шестом приведено другое имя сценария:
12000 stream tcp wait nobody /usr/local/bin/eliza_jlnetd.pl eliza inetd.pl
Этот сервер не только наследует приемный сокет от демона inetd, но и отличается от предыдущих версий тем, что предусматривает минутный тайм-аут при вызове функции accept (). Если в течение этого тайм-аута не поступит ни одного нового соединения, родительский процесс завершится и демон inetd повторно запустит сервер, когда он снова потребуется. Изменения, которые пришлось внести в основной сервер с ветвлением, оказались незначительными. Подобным сервером можно обрабатывать множественные запросы, например, на хост, содержащий информацию об высокопроизводительных принтерах HP или с другой информацией.
И так проведем анализ программы.
1) Определение значений тайм-аута. Значение тайм-аута берется из командной строки или устанавливается по умолчанию равным одной минуте, если соответствующий параметр не задан. Обратите внимание, что номер порта больше не считывается из командной строки, поскольку значение этого параметра неявно передается демоном inetd.
2) Восстановление дескриптора приемного сокета. Значение дескриптора приемного сокета восстанавливается из дескриптора stdin. Вначале происходит проверка, действительно ли этот сценарий выполняется под управлением inetd, путем определения того, что дескриптор stdin является сокетом, с использованием опции файловой проверки -s. Если дескриптор stdin проходит эту проверку, он снова преобразуется в объект IO::Socket путем вызова метода new_from_fd() модуля IO::Socket. Этот метод, унаследованный от модуля IO:: Handle, аналогичен методу fdopen (), за исключением того, что, вместо переоткрытия существующего дескриптора на базе указанного дескриптора файла, он создает новый дескриптор, который является копией старого. В этом случае создается новый объект IO::Socket, который является копией дескриптора stdin, открытого для чтения и записи.