На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
    > сокеты: connect и таймаут
      Здравствуйте.

      Меня интересует, можно ли для сокета, используемого в вызове connect() задать значение таймаута. Все дело в том, что мне нужно перебрать некоторое кол-во адресов в достаточно большой локальной сети, на предмет наличия по этим адресам некоторых открытых портов (сканирование). Если сервис отсутствует, то вызов connect() занимает уж больно продолжительный отрезок времени...

      Спасибо.
        Использую функцию select - самый быстрый вариант сканирования + использование потоков. Удачи!
            Rara Avis, используй потоки или асинхронные сокеты.
              Спасибо, про потоки я уже думал.
                Rara Avis,
                1. У вызова connect() в Windows нет конфигурированного таймаута. Он зашит в алгоритм TCP-модуля. В некоторых Unix-like системах это возможно.
                2. Вам надо создать массив сокетов и запускать на отдельном сокете асинхронную функцию WSAConnect, используя модель с перекрытием - т.е. позапускать кучу коннектов и "бросить их на попечение системы".
                3. Модель исполнения операций ввода/вывода с перекрытием (ее также называют моделью совмещенных операций) – Overlapped I/O. Она реализуется только на сокетах, которые при формировании были объявлены для исполнения на них совмещенных операций c помощью функции WSASocket():
                SOCKET WSASocket(
                int af,
                int type,
                int protocol,
                LPWSAPROTOCOL_INFO lpProtocolInfo,
                GROUP g,
                DWORD dwFlags);
                Придется создать свои сообщения и привязать их к событию FD_CONNECT.
                Очень хорошо все это описано в книге Оланда (Olund) Оланд Д., Джонс Э. Программирование в сетях Microsoft Windows , ISBN: 5-318-00725-2 издательство "Питер", 2002, или в английской версии второго издания - Jones A., Ohlund J., Ohlund Jim Network Programming for Microsoft Windows, Second Edition Microsoft Press, February 13, 2002 ISBN: 0735615799, ее можно найти в Интернете? или пиринговых сетях в формате .chm.
                Завершение обработки ввода/вывода с перекрытием может выполняться двояким способом – или приложение ждет оповещения о возникновении сетевого события в event-объекте, или приложение обрабатывает сетевую ситуацию при помощи специальной "процедуры завершения", на которую указывает специальный параметр типа WSAOVERLAPPED_COMPLETION_ROUTINE. Этот параметр необязателен и представляет собой указатель на специальную функцию, которая вызывается после завершения нужной операции и обрабатывает ее данные.
                Для метода оповещения в помощью объектов-событий WinSock изменяет состояние данного объекта, ассоциированное о структурой WSAOVERLAPPED в "просигналенное", когда запрос на операцию ввода/вывода наконец завершится. Отслеживание этого момента приложение лучше производить при помощи функции WSAWaitForMultipleEvents(). Определив, что операция завершилась, надо определить и ее статус – успешное завершение или нет – с помощью функции WSAGetOverlappedResult():
                BOOL WSAGetOverlappedResult(
                SOCKET sd,
                LPWSAOVERLAPPED lpOverlapped,
                LPDWORD lpcbTransfer,
                BOOL fWait,
                LPDWORD lpdwFlags
                );
                Параметр lpOverlapped указывает на структуру WSAOVERLAPPED, определенную при инициировании операции. Параметр lpcbTransfer указывает на переменную, в которой фиксируется фактическое количество принятых или посланных байт. Параметр fWait определяет поведение функции – должна ли она ожидать, если операция на момент проверки еще не завершилась, или нет. При fWait=TRUE функция не вернет управление вплоть до завершения операции. При fWait=FALSE и еще продолжающейся операции функция возвращает FALSE с индикацией ошибки WSA_IO_INCOMPLETE. Так как в данном случае функция вызывается для уже "свершившегося" события, этот параметр не имеет последствий. Последний параметр lpdwFlags является указателем на переменную, в которую помещаются результирующие значения флагов, если вызов с перекрытием был выполнен функциями WSARecv() или WSARecvFrom().
                При успешном завершении операции WSAGetOverlappedResult() возвращает TRUE. Если она возвращает FALSE, то:
                · Или I/O-операция еще выполняется.
                · Или I/O-операция завершилась, но с ошибками.
                · Или статус завершения I/O-операции не может быть определен из-за сопутствующих ошибок в параметрах WSAGetOverlappedResult().
                Все это непросто, но - успехов!
                  Огромное спасибо за столь подробный ответ. Удачи!
                    Привет, тема довольно старая но народ роеться в форуме, поэтому может кому пригодиться...

                    Я использую вместо стандартного connect свою обертку, тотже connect но последний параметр время ожидания

                    ExpandedWrap disabled
                      int connectex(SOCKET s1, const struct sockaddr *name,
                                                  int namelen, long timeout)
                      {
                          // As connect() but with timeout setting.
                          int            rc = 0;
                          ULONG          ulB;
                          struct timeval Time;
                          fd_set         FdSet;
                       
                          ulB = TRUE; // Set socket to non-blocking mode
                          ioctlsocket(s1, FIONBIO, &ulB);
                       
                          if (connect(s1, name, sizeof(SOCKADDR)) == SOCKET_ERROR) {
                       
                              if (WSAGetLastError() == WSAEWOULDBLOCK) {
                                  // now wait for the specified time
                                  FD_ZERO(&FdSet);
                                  FD_SET(s1, &FdSet);
                       
                                  Time.tv_sec  = timeout / 1000L;
                                  Time.tv_usec = (timeout % 1000) * 1000;
                                  rc = select(0, NULL, &FdSet, NULL, &Time);
                       
                              }
                          }
                       
                          ulB = FALSE; // Restore socket to blocking mode
                          ioctlsocket(s1, FIONBIO, &ulB);
                       
                          return (rc > 0) ? 0 : SOCKET_ERROR;
                      }
                      connectex пригодилась, спасибо )
                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                      0 пользователей:


                      Рейтинг@Mail.ru
                      [ Script execution time: 0,0260 ]   [ 17 queries used ]   [ Generated: 26.04.24, 10:28 GMT ]