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