Вначале рассмотрим основной сценарий. В сценарии web_fetch_p.pl используются неблокирующие подключения для распараллеливания выборки URL
#!/usr/local/bin/perl -w . # Файл: web_fetch_p.pl use strict; use HTTPFetch; use IO::Socket; use IO::Select; my. %CONNECTIONS; # Отображение "сокет => объект" # Создать два объекта IO::Select для чтения и записи my $readers = IO::Select->new; my $writers = IO::Select->new; # Создать соединения из списка URL в командной строке while (my $url = shift) { next unless my $object = HTTPFetch->new ($url) ; $CONNECTIONS{$object->socket} = $object; # Запомнить сокет $writers->add($object->socket); # Следить за выполнением в нем операций записи while (my ($readable,$writable) = IO::Select->select($ readers,$writers)) { foreach (@$writable) { # Дескриптор готов для записи my $obj = $CONNEGTIONS{$_}; # Получить объект HTTP my $result = $obj->send_request; # Попытаться отправить запрос $readers->add ($_) if $result; # Запрос отправлен успешно, поэтому контролировать готовность к чтению $writers->remove($_); # и удалить из списка контролируемых для записи foreach (@$readable) { # Дескриптор готов для чтения my $obj = $CONNECTIONS{$_}; # Получить объект HTTP my $result = $obj->read; # Прочитать данные unless ($result) { # Удалить дескриптор, если произошла ошибка $readers->remove($_); delete $CONNECTIONS{$_} ; }} last unless $readers->count or $writers->count; .# Выйти из программы, если вся работа выполнена }
Проведем анализ программы.
Строки 1-6. Инициализация сценария. Выполнение начинается с загрузки модулей IO::Socket, IO::Select и HTTPFetch. Объявляется также глобальный хеш %connections, который отвечает за обмен информацией между сокетами и объектами HTTPFetch.
Строки 7-9. Создание объектов IO::Select. Теперь создаются два набора объектов IO::Select. Один из них позволяет контролировать готовность сокетов для чтения, а другой — для записи.
Строки 10-15. Создание объектов соединения HTTPFetch. В следующем разделе кода из командной строки считывается набор URL. Для каждого из них создается новый объект HTTPFetch путем вызова метода HTTPFetch->new () с указанием URL, который должен быть выбран.
Метод HTTPFetch->new() выполняет большой объем работы незаметно для постороннего взгляда. Он интерпретирует URL, создает сокет TCP и инициализирует неблокирующее соединение с соответствующим хостом Web-cepeepa. Если любой из этих этапов закончится аварийно, метод new () возвращает значение undef и происходит переход к следующему URL. В ином случае метод new () возвращает новый объект HTTPFetch.
Каждый объект HTTPFetch имеет метод socket (), который возвращает свой основополагающий объект IO::Socket. Этот сокет будет контролироваться в целях определения момента завершения неблокирующего подключения. Данный сокет добавляется к набору $writers объекта IO::Select и информация о том, что этот сокет и объект HTTPFetch связаны между собой, запоминается в хеше %connections.