Общая схема реализации такого подхода показана в следующем фрагменте кода. В нем создаются три сокета, соответственно, привязанные к портам 80, 8000 и 8080 (эти порты обычно применяются в Web-cepвepax).
my $sock80 = IO::Socket::INET->new( LocalPort => 80, Listen => 20, Reuse => 1); my $sock8000 = IO::Socket::INET->new( LocalPort => 8000, Listen =>20, Reuse => 1) ; my $sock8080 = IO::Socket::INET->new( LocalPort => 8080, Listen | => 20, Reuse =>1); # Каждый сокет отмечается как неблокирующий и добавляется к модулю IO::Select, foreach ($sock80,$sock8000,$sock8080) { $_->blocking(0); }
В главном цикле вызывается метод can_read () объекта IO::Select и создается список сокетов, готовых для выполнения метода accept (). Вызывается функция accept () каждого готового сокета и обслуживается подключенный сокет, который возвращен из анонимной подпрограммы путём перевода его снова в блокирующий режим и передачи некоторой процедуре, которая обрабатывает это соединение.
Возможно также, что метод accept () возвратит значение undef и установи код ошибки EWOULDBLOCK, даже если метод select () покажет, что сокет готов для чтения. Это может произойти, если удаленный хост разорвал соединение между возвратом из метода select () и вызовом метода accept (). В этом случае просто выполняется переход в начало цикла, и попытка чтения из сокета повторяется позднее.
while (1) { my @ready = $listeners->can_read; foreach (@ready) { next unless my $connected = $_->accept(); $connected->blocking(1); handle_connection ($connected) }}
И так подведем итоги. Неблокирующий ввод-вывод — обоюдоострый меч. С одной стороны, он позволяет создавать серверы, которые могут обслуживать одновременно несколько соединений, порождая новые процессы или потоки, которые могут работать с различной информацией, например, получение контента страницы http://www.sistyle.ru , представляющей IT услуги для среднего и малого бизнеса. По сравнению с мультипроцессными решениями, неблокирующий ввод-вывод обеспечивает небольшое повышение производительности и потребляет меньшее количество системных ресурсов. Он является также единственным возможным решением по созданию серверов, обслуживающих большое число соединений, на платформах, не поддерживающих функцию fork () и многопоточный API-интерфейс, таких как Macintosh.
С другой стороны, неблокирующий ввод-вывод значительно повышает сложность программного обеспечения. В основном это связано с тем, что в программе приходится следить за частично выполненными операциями записи и обрабатывать флаги EWOULDBLOCK, возникающие при вызове функций syswrite () и sysread (). Примеры сценариев, представленные выше принадлежат к числу самых длинных программ этого раздела, и для их разработки и отладки потребовалось очень много времени. Специалисты почти всегда предпочитают мультипроцессные или многопоточные решения неблокирующему вводу-выводу. Неблокирующий ввод-вывод может также использоваться для предотвращения блокировки вызовов функций connect () и accept (). Это позволяет применять к таким вызовам тайм-ауты и распараллеливать попытки соединения без значительно увеличения размера и повышения сложности программного обеспечения.