The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

Задание таймаута в Perl модуле Socket (socket connect timeout perl select)


<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>
Ключевые слова: socket, connect, timeout, perl, select,  (найти похожие документы)
Date: Tue, 05 Nov 2002 19:10:21 +0500 From: Andrey Sapozhnikov <sapa@icb.chel.su> Newsgroups: ftn.ru.perl Subject: Задание таймаута в Perl модуле Socket > Для проверки доступности порта на удаленном хосте я использую > модуль Socket. Hо мне хотелось бы задать таймаут на установление исходящего > соединения TCP. Однако, ни среди параметров функции connect(), ни среди опций > сокета, устанавливаемых посредством setsocktopt(), я не обнаружил параметра, > определяющего таймаут на установление соединения. > > Предусмотрен ли вообще такой параметр? > Если ли нет, то каким образом можно установить требуемый таймаут, кроме > очевидного решения с применением $SIG{ALRM}? Гораздо лучше реализовать подобный таймаут с помощью select. use strict; use Socket; use Fcntl; use Errno; my $proto = getprotobyname('tcp'); socket(SOCK, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; my $sin = sockaddr_in(80, inet_aton('192.168.0.1')); # bind можно опустить, тогда будет неявно вызван # bind(SOCK, sockaddr_in(0, INADDR_ANY)) # Теперь переводим сокет в non-block mode fcntl(SOCK, F_SETFL, O_NONBLOCK) or die "fcntl: $!"; unless (connect(SOCK, $sin)) { # Hекоторые системы возвращают EWOULDBLOCK вместо EINPROGRESS Errno::EINPROGRESS == $! or Errno::EWOULDBLOCK or die "connect: $!"; vec(my $win = '', fileno(SOCK), 1) = 1; # Таймаут соединения - десять с половиной секунд unless (select(undef, $win, undef, 10.5)) { close (SOCK); die "Time is out!\n"; } if (defined (my $ret = getsockopt(SOCK, SOL_SOCKET, SO_ERROR))) { die "connection failed: $!" if $! = unpack('i', $ret); # Hе во всех системах поддерживается SO_ERROR # fallback до getpeername } elsif (!getpeername(SOCK)) { die "connection failed: $!"; } } fcntl(SOCK, F_SETFL, 0); Если требуется что-то после этого читать-писать из сокета, и конкретный тип ошибки соединения не важен, то можно выбросить все проверки на ошибки после select, и ориентироваться на то, что вернет read или write. При этом надо иметь в виду, что в некоторых системах запись в неоткрытый сокет вызовет сигнал SIGPIPE котоый нужно будет обработать или игнорировать. Если писать ничего не требуется, то можно сэкономить последнюю строчку и не снимать O_NONBLOCK :-) А в общем, я рекомендовал бы именно так.

<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>

Обсуждение [ RSS ]
  • 1, JIP (??), 10:43, 22/01/2007 [ответить]  
  • +/
    код неработоспособен в ActivePerl 5.8.7

    'Your vendor has not defined Fcntl macro F_SETFL, used at line 14.'

     
  • 2, pwn (??), 20:02, 19/08/2007 [ответить]  
  • +/
    Прекрасно работает!

    Автору респект, я его методом вылечил модуль HTTP-Lite 2.1.6 от пагубного пристрастия крутить дефолтный таймаут в 189 секунд !

    Работает как в обяном перле, так и в ActivePerl 5.8.8, в том числе и прекрасно компилируется ихней утилитой PDK!

     
  • 3, TnT (??), 21:23, 18/08/2009 [ответить]  
  • +/
    Реально помогло, хоть и не для перла, спасибо!
     
  • 4, mnikolenko (?), 16:14, 03/04/2010 [ответить]  
  • +/
    Спасибо!
     

     Добавить комментарий
    Имя:
    E-Mail:
    Заголовок:
    Текст:




    Спонсоры:
    Inferno Solutions
    Hosting by Hoster.ru
    Хостинг:

    Закладки на сайте
    Проследить за страницей
    Created 1996-2020 by Maxim Chirkov
    Добавить, Поддержать, Вебмастеру