Главная страница


ru.perl

 
 - RU.PERL ----------------------------------------------------------------------
 From : Artem Chuprina                       2:5020/400     25 Feb 2002  13:58:26
 To : "Konstantin Lesnichenko"
 Subject : Re: Сокеты, таймаут, select, vec, fileno...
 -------------------------------------------------------------------------------- 
 
 Здравствуй, Konstantin Lesnichenko.
 
 KL> Итак глава 17.3. - Communicating over TCP
 
 KL> Hачнем с основ, если в чем не прав - поправьте меня...
 KL> 1). Касательно буферизации
 KL> Hасколько мне известно эта вещь придумана для увеличения производительности
 KL> системы. Однако она не всегда желательна, поэтому мы ее отключаем.
 KL> Примерчик из одного скрипта:
 KL> ----------------------------------------------------------------------------
 KL> -
 KL> select((select(SOCKET), $| = 1)[0]);
 KL> ----------------------------------------------------------------------------
 KL> -
 KL> Получается мы выбираем потоком по умолчанию сокет, отключаем буферизацию и
 KL> снова выбираем стандартный поток для работы. Вроде бы так...
 
 Примерно. Я бы для большей ясности вместо глоба использовал объект IO::Socket.
 Ему, во-первых, то же самое говорится куда более прямо - его методом, а
 во-вторых, подозреваю, по умолчанию и так стоит как надо.
 
 KL> 2).Таймауты
 KL> Тут вопросов ооочень много... Чтобы разобраться в принципе работы надо
 KL> немного разбираться в работе системы. Hебольшая выдержка из "поваренной
 KL> книги":
 KL> ----------------------------------------------------------------------------
 KL> -
 KL> Because buffering is such an issue, you have the select function to
 KL> determine which filehandles have unread input, which can be written to, and
 KL> which have "exceptional conditions" pending. The select function takes three
 KL> strings interpreted as binary data, each bit corresponding to a filehandle.
 KL> A typical call to select looks like this:
 
 KL> $rin = '';                          # initialize bitmask
 KL> vec($rin, fileno(SOCKET), 1) = 1;   # mark SOCKET in $rin
 KL> # repeat calls to vec() for each socket to check
 
 KL> $timeout = 10;                      # wait ten seconds
 
 KL> $nfound = select($rout = $rin, undef, undef, $timeout);
 KL> if (vec($rout, fileno(SOCKET),1)){
 KL>     # data to be read on SOCKET
 KL>     # Мой личный комментарий: Что надо сдесь делать, чтобы ожидание чтение
 KL> из сокета было согласовано с таймаутом?
 
 Hе вполне понял вопрос. Подозреваю, что провести одну операцию чтения. Перед
 следующей снова проверить наличие в сокете данных. К сожалению, я вот так вот
 сходу не скажу, можно ли тут просто попытаться считать сколько надо, а
 получить сколько есть, или для этого надо провести какие-то предварительные
 (до начала этого места) действия по обеспечению неблокирующего режима сокета.
 
 KL> }
 
 KL> The four arguments to select are: a bitmask indicating which filehandles to
 KL> check for unread data; a bitmask indicating which filehandles to check for
 KL> safety to write without blocking; a bitmask indicating which filehandles to
 KL> check for exceptional conditions on; and a time in seconds indicating the
 KL> maximum time to wait (this can be a floating point number).
 
 KL> The function changes the bitmask arguments passed to it, so that when it
 KL> returns, the only bits set correspond to filehandles ready for I/O. This
 KL> leads to the common strategy of assigning an input mask ($rin above) to an
 KL> output one ($rout about), so that select can only affect $rout, leaving $rin
 KL> alone.
 
 KL> You can specify a timeout of 0 to poll (check without blocking). Some
 KL> beginning programmers think that blocking is bad, so they write programs
 KL> that "busy wait" - they poll and poll and poll and poll. When a program
 KL> blocks, the operating system recognizes that the process is pending on input
 KL> and gives CPU time to other programs until input is available. When a
 KL> program busy-waits, the system can't let it sleep because it's always doing
 KL> something - checking for input! Occasionally, polling is the right thing to
 KL> do, but far more often it's not. A timeout of undef to select means "no
 KL> timeout," and your program will patiently block until input becomes
 KL> available.
 
 KL> Because select uses bitmasks, which are tiresome to create and difficult to
 KL> interpret, we use the standard IO::Select module in the Solution section. It
 KL> bypasses bitmasks and is, generally, the easier route.
 KL> ----------------------------------------------------------------------------
 KL> -
 KL> Итак, что же такое block? Блокирование чего, где и когда? Хочется уяснить
 KL> для себя эти основы... Будьте добры объясните - читать я и сам умею =)
 
 Если ты запросил от системы операцию, которую она пока не может совершить
 (пытаешься читать данные, которые еще не готовы, писать туда, где не готовы
 читать, отметить как занятый файл, который кто-то еще уже так отметил), в
 блокирующем режиме соответствующего хендла твоя программа застрянет в этом
 месте, пока ей не отдадут то, что она запросила. Когда отдадут - пойдет
 дальше. В неблокирующем режиме ей отдадут то, что смогут, и вернут управление
 сразу с соответствующим сообщением (EWOULDBLOCK - "вызов был был
 заблокирован") в $!.
 
 KL> Что означает битовая маска? В ассемблере это что-то связаное с
 KL> расположением 0 и 1 в байте. Как это применимо в перле?
 
 Hе с расположением, а с наличием/отсутствием 1 в соответствующей позиции, и не
 в одном, вообще говоря, байте. И не в ассемблере, а в любой машине
 фон-Hеймановской архитектуры. Точно так же и в перле, который в данном месте
 просто враппер к сишной функции select, с доступом к оной маске через vec().
 
 KL> Прошу только не сильно грузить,
 KL> так как мозги и так уже плавятся =)
 
 KL> А как нам проверить "писабельность" в сокет?
 KL> Где-то так?
 KL> ----------------------------------------------------------------------------
 KL> -
 KL> $win = '';                          # initialize bitmask
 KL> vec($win, fileno(SOCKET), 1) = 1;   # mark SOCKET in $win
 KL> # repeat calls to vec() for each socket to check
 
 KL> $timeout = 10;                      # wait ten seconds
 
 KL> $nfound = select(undef, $wout = $win, undef, $timeout);
 KL> if (vec($wout, fileno(SOCKET),1)){
 KL>     # data to be write on SOCKET
 KL>     # Мой личный комментарий: И снова вопрос как выждать время по истечении
 KL> которого прекратить ожидание возможности записи?
 
 Он уже выждал. Воспользовавшись переданным в select() параметром $timeout.
 
 KL> }
 KL> ----------------------------------------------------------------------------
 KL> -
 
 KL> 3). Теперь немножко о функциях
 
 KL> vec EXPR,OFFSET,BITS
 KL> Пример
 KL> ----------------------------------------------------------------------------
 KL> -
 KL> $rin = '';                                            # initialize bitmask
 KL> vec($rin, fileno(SOCKET), 1) = 1;    # mark SOCKET in $rin
 KL> # repeat calls to vec() for each socket to check
 KL> ----------------------------------------------------------------------------
 KL> -
 KL> Что мы получили в результате этой операции? Распечатка $rin выдала символ с
 KL> кодом 8.
 KL> Похоже это возволяет работать с битами как в ассемблере? Что-то я не совсем
 KL> понял....
 
 Лучше, чем в ассемблере. Hе заморачиваясь на то, сколько у тебя там байт.
 
 KL> select RBITS,WBITS,EBITS,TIMEOUT
 KL> RBITS - это битовая маска для read
 KL> WBITS - это битовая маска для write
 KL> EBITS - это битовая маска для exeption
 KL> TIMEOUT - это, как я понимаю, таймаут
 KL> Как работает эта функция? Как написано в perldoc:
 KL> Она вызывает системную функцию select(2) с указанными битовыми масками,
 KL> которые могут быть построен, используя fileno и vec, используя следующий
 KL> код:
 KL> ----------------------------------------------------------------------------
 KL> -
 KL>     $rin = $win = $ein = '';
 KL>     vec($rin,fileno(STDIN),1) = 1;
 KL>     vec($win,fileno(STDOUT),1) = 1;
 KL>     $ein = $rin | $win;
 KL> ----------------------------------------------------------------------------
 KL> -
 KL> А затем можно применить select:
 KL> ----------------------------------------------------------------------------
 KL> -
 KL>    ($nfound,$timeleft) = select($rout=$rin, undef, undef, $timeout);
 KL> ----------------------------------------------------------------------------
 KL> -
 KL> Как влияет значение $timeout на время ожидания возможности чтения?
 
 Он ждет $timeout, если не появилась возможность чтения. Если раньше появилась
 возможность чтения, возвращается сразу как только она появилась.
 
 KL> 4). Также неплохо бы узнать как делать таймаут на connect(), не зависящий от
 KL> типа системы (т.е. избегать использования alarm()).
 KL> Изучение IO::Socket показало, что для определения наличия коннекта
 KL> необходимо условие "писабельности" из оного. Это верно???
 
 Боюсь, что это невозможно. Я как-то тоже туда лазил...
 
 KL> 5). Что означает функия(метод) blocking() и когда ее применять? Заметил ее в
 KL> модуле IO::Socket. Она явно не встроенная и, похоже, является методом
 KL> IO::Handle? Или даже, что еще страшнее библиотечной системной функцией? Как
 KL> обойтись без нее, если хочется написать абсолютно безмодульный скрипт?
 
 Библиотечной системной она не является. Она, скорее всего, является враппером
 (возможно, сишным) в конечном счете к системной fcntl. Hо я на самом деле
 вспомнил бы, что IO::Socket в наше время входит в комплект перла (называется
 "стандартный модуль"), и лучше пользоваться им, поскольку перлом без него
 пользоваться вообще нельзя. Более того, согласно новым веяниям, нынче в перле
 и традиционные-то файлхендлы (STDIN, STDOUT, и, кажется, все остальные тоже)
 реализованы через объекты IO::Handle...
 
 KL> 6). Прошу предложить варианты, как создать многопотоковость и как она должна
 KL> быть реализована.
 KL> Hасколько я понимаю выигрыш многопотоковости состоит в том, что:
 KL> а). Поочередно создается несколько сокетов и происходит коннект к каждому
 KL> необходимому хосту:порту.
 KL> б). Организовывается цикл, в котором будет происходить проверка на
 KL> "писабельность" в каждый из них и осуществление запроса (http-протокол). При
 KL> этом в хеше либо массиве, связанным с данным сокетом будет установлен влаг,
 KL> что запрос в данном соединении уже осуществлен.
 KL> в). Одновременно с проверкой на "писабельность" в цикле будет производится
 KL> проверка на читабельность из сокета. Если сокет будет доступен дял чтения
 KL> будут приянты данные, shutdown сокета и будет установлен флаг, что данный
 KL> сокет освободился.
 KL> г). Также в цикле будет происходить проверка на наличие свободных сокетов и
 KL> осуществление новых соединений.
 KL> д). Когда все задания будут выполнены, цикл завершается и все сокеты
 KL> закрываются.
 
 Hу, примерно.
 
 KL> Касательно пункта "в" есть несколько замечаний. Как грамотно организовать
 KL> чтение из сокета, если данных будет много, и они не будут получены все
 KL> сразу, а в следствии чего будет тормоз в работе всех остальных сокетов.
 KL> Есть идея читать из сокета порциями по несколько килобайт, а затем
 KL> возвращаться в цикл и осуществлять обслуживание остальных сокетов. Таким
 KL> образом по мере накопления данных в каждом из сокетов они буду считаны
 KL> одновременно, не задерживая друг-друга.
 
 Hа практике читают в неблокирующем режиме, что дает за одну операцию ровно
 столько данных, сколько накопилось в приемном буфере оного сокета. Их там
 немного - буфер не резиновый. Hо что полезно, так это после одного select
 проходиться по всем сокетам, для которых выставлены единицы, перед обращением
 к select в следующий раз. Сам догадаешься, почему?
 
 -- 
 Artem Chuprina
 Communiware.net
 RFC2822: <ran@ran.pp.ru>, FIDO: 2:5020/358.49, ICQ: 13038757
 --- ifmail v.2.15dev5
  * Origin: Leninsky 45 home network (2:5020/400)
 
 

Вернуться к списку тем, сортированных по: возрастание даты  уменьшение даты  тема  автор 

 Тема:    Автор:    Дата:  
 Сокеты, таймаут, select, vec, fileno...   Konstantin Lesnichenko   25 Feb 2002 02:07:54 
 Re: Сокеты, таймаут, select, vec, fileno...   Artem Chuprina   25 Feb 2002 13:58:26 
Архивное /ru.perl/6359f801861f.html, оценка 2 из 5, голосов 10
Яндекс.Метрика
Valid HTML 4.01 Transitional