Как использовать select() для проверки - "открыт ли порт"?

Тема в разделе "WASM.BEGINNERS", создана пользователем _sheva740, 5 сен 2007.

  1. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    Добрый день!

    Проверяю заданный IP - на открытый 25 порт.
    Пишу функцию - на вход подаю интерес. IP
    - на выходе

    0 - порт 25 открыт
    -1 - порт 25 закрыт

    Код (Text):
    1.  
    2. _smtptest proc _strIP:DWORD
    3. LOCAL _strIP_  [50]:BYTE
    4. LOCAl time_out : timeval
    5. LOCAL fds : fd_set
    6.     invoke  lstrcpy,ADDR _strIP_, [_strIP]
    7.     invoke  WSAStartup,101h,offset wsadata
    8.  
    9.     invoke  socket,AF_INET,SOCK_STREAM,0
    10.     mov sock,eax
    11.     mov s_addr.sin_family,AF_INET
    12.     invoke  htons,25
    13.     mov s_addr.sin_port,ax
    14.     invoke  inet_addr,ADDR  _strIP_
    15.     mov s_addr.sin_addr,eax
    16.  
    17.     invoke  connect,sock,addr s_addr,sizeof s_addr
    18.  
    19. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    20.  
    21.  
    22.     xor edx, edx
    23.     mov time_out.tv_sec, 1      ; структура, определяющая, сколько
    24.     mov time_out.tv_usec, 500       ; времени select будет ждать окончания
    25.                         ; ввода-вывода
    26.  
    27.     mov dword ptr [fds.fd_count], 1
    28.     push    sock
    29.     pop fds.fd_array
    30.  
    31.     invoke  select, 0, ADDR fds, edx, edx, ADDR time_out    ; Ждем 500 ms
    32.     test    eax, eax                ; Если данные не поступили
    33.     jz  ___quit1                ; то переходим
    34.  
    35.  
    36. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    37.     invoke  recvfrom, sock, ADDR r_buf, 512, 0, addr s_addr, sizeof s_addr
    38.     cmp dword ptr [r_buf],' 022'
    39.     jz  ___quit0
    40.  
    41. ___quit1:
    42.     invoke  closesocket,sock  
    43.     invoke  WSACleanup
    44.     xor eax,eax
    45.     mov eax,-1              ; 25 - закрыт
    46.     ret
    47. ___quit0:
    48.     invoke  closesocket,sock
    49.     invoke  WSACleanup
    50.     xor eax,eax             ; 25 - открыт
    51.     ret
    52.     ;------------------------------------
    53.     ;------------------------------------
    54.  
    55. _smtptest endp
    Подставляю IP - 194.67.23.20 - Это smtp.mail.ru

    Проверил :
    Код (Text):
    1.  
    2. c:/> telnet  194.67.23.20
    3. 220 Mail.Ru ESMTP
    4. .
    5. .
    6. .
    то есть 25 порт открыт. А у меня он закрыт получаестя :dntknw:(
    Может я неправильно пользуюсь функцией select()?
    Вроде как все делаю по книге
    Йон Снейдеp "Эффективное пpогpаммиpование TCP/IP".
    25-совет использование select().
     
  2. nester7

    nester7 New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2003
    Сообщения:
    720
    Адрес:
    Russia
    1. если коннект прошел успешно (invoke connect,sock,addr s_addr,sizeof s_addr),
    значит порт открыт. Где проверка на успешность?
    2. WSAGetLastError() что говорит после твоего селекта?

    а вообще:
    Код (Text):
    1. _smtptest proc _strIP:DWORD
    2.  
    3. LOCAL _strIP_  [50]:BYTE
    4.  
    5.     invoke  lstrcpy,ADDR _strIP_, [_strIP]
    6.     invoke  WSAStartup,101h,offset wsadata
    7.  
    8.     invoke  socket,AF_INET,SOCK_STREAM,0
    9.     mov sock,eax
    10.     mov s_addr.sin_family,AF_INET
    11.     invoke  htons,25
    12.     mov s_addr.sin_port,ax
    13.     invoke  inet_addr,ADDR  _strIP_
    14.     mov s_addr.sin_addr,eax
    15.  
    16.     invoke  connect,sock,addr s_addr,sizeof s_addr
    17.            ret
    18. _smtptest endp
     
  3. dimonn

    dimonn New Member

    Публикаций:
    0
    Регистрация:
    5 мар 2006
    Сообщения:
    38
    Адрес:
    Sim-City
    select используется не для "проверки открыт ли порт", а для опроса массива сокетов на предмет их готовности для операций синхронного ввода-вывода. На первый взгляд в коде боков вроде нету, так что дебаггер те в руки и вперед...

    И вообще, походу, recvfrom здесь для твоей задачи избыточен. Если select вернул не ноль, то ответ пришел, прыгай сразу на quit0.
     
  4. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    nester7
    да я вообще-то с этим select - том вожусь чтоб как-то ускорить работу функции с "неправильными" ip.
    Но кажется что с select() что без него "неправильные" ip где-то секунду так и обрабатываются.

    dimonn

    > для опроса массива сокетов на предмет их готовности для операций синхронного ввода-вывода

    вот я же и добавил его в массив, и проверяю на предмет готовности к вводу-выводу
    Код (Text):
    1. ...
    2.     mov dword ptr [fds.fd_count], 1
    3.     push    sock
    4.     pop fds.fd_array
    5. ...
    > вообще, походу, recvfrom здесь для твоей задачи избыточен.

    да, верно, спасибо. Я просто эту проверку для пущей уверенности поставил :)
     
  5. nester7

    nester7 New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2003
    Сообщения:
    720
    Адрес:
    Russia
    Эээ... походу тебе нужны неблокируемые сокеты.

    Рано ещё, книжек почитай, Стивенса к примеру :)
     
  6. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    nester7
    > книжек почитай, Стивенса к примеру
    Как конкретней книга называется ?
     
  7. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    _sheva740
    Что значит неправильные IP? Не существующие чтоли? Так они по другому определяются. Пингом например. А селект для проверки открытых портов совсем незачем. Или тебе всё же данные надо получать? Тогда можно.
    nester7
    Зачем неблокируемые сокеты? Время cpu кушать?
     
  8. nester7

    nester7 New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2003
    Сообщения:
    720
    Адрес:
    Russia
  9. nester7

    nester7 New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2003
    Сообщения:
    720
    Адрес:
    Russia
    Вообще-то нет, наоборот. Читаем книги,
    кодим и думаем.
     
  10. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    nester7
    Нашел У. Р. Стивенс ...UNIX. Разработка сетевых приложений
    Читал избарательно.
    Приведу выдержки -

    Глава 13.2 - Тайм - ауты сокета
    Раздел Тайм - аут для функции connect().

    [...] Функцию selest() можно использовать для установки тайм-аута функции connect(), только когда сокет находится в неблокируемом режиме [...]

    Листинг 13.3. Функция readable_timeo: ожидание, когда дескриптор станет готов
    для чтения
    Код (Text):
    1. //lib/readable_timeo.с
    2. #include    "imp.h"
    3. int readable_timeo(int fd, int sec)
    4.  {
    5.    fd_set   rset;
    6.    struct timeval tv;
    7.  
    8.    FD_ZERO(&rset);
    9.    FD_SET(fd, &rset);
    10.    tv.tv_sec   =sec;
    11.    tv.tv_usec  =0;
    12.    return (select(fd + 1, &rset, NULL, NULL, &tv));
    13.  }
    Все как бы делаю правильно.
    Поэтому исправил свою функцию :

    Код (Text):
    1. _smtptest proc _strIP:DWORD
    2. LOCAL _strIP_  [50]:BYTE
    3. LOCAl time_out : timeval
    4. LOCAL fds : fd_set
    5. LOCAL dwZero : DWORD
    6.     invoke  lstrcpy,ADDR _strIP_, [_strIP]
    7.     invoke  WSAStartup,202h,offset wsadata
    8.  
    9.     invoke  socket,AF_INET,SOCK_STREAM,0
    10.     mov sock,eax
    11. ;------------------------------------
    12.     mov dwZero,1
    13.     invoke  ioctlsocket, sock, FIONBIO, ADDR dwZero
    14. ;------------------------------------
    15.  
    16.     mov s_addr.sin_family,AF_INET
    17.     invoke  htons,25
    18.     mov s_addr.sin_port,ax
    19.     invoke  inet_addr,ADDR  _strIP_
    20.     mov s_addr.sin_addr,eax
    21.  
    22.     invoke  connect,sock,addr s_addr,sizeof s_addr
    23.     xor edx, edx
    24.     mov time_out.tv_sec, 1;1        ; структура, определяющая, сколько
    25.     mov time_out.tv_usec, 0;500     ; времени select будет ждать окончания
    26.                         ; ввода-вывода
    27.  
    28.     mov dword ptr [fds.fd_count], 1
    29.     push    sock
    30.     pop fds.fd_array
    31.  
    32.     invoke  select, 0, ADDR fds, edx, edx, ADDR time_out    ; Ждем 1s
    33.     cmp eax, 1              ; Если select() вернул 1
    34.                         ; - значит один сокет готов к работе
    35.     je  ___quit0            ; то переходим на +OK
    36. ___quit1:
    37.     invoke  closesocket,sock
    38.     xor eax,eax
    39.     mov eax,-1
    40.     ret
    41. ___quit0:
    42.     invoke  closesocket,sock
    43.     xor eax,eax
    44.     ret
    45. _smtptest endp
    Запускаю 10 раз на smtp.mail.ru
    Код (Text):
    1. C:\_temp\_smtpTest>_mailrep_use.exe
    2. 194.67.23.20    -
    3. C:\_temp\_smtpTest>_mailrep_use.exe
    4. 194.67.23.20    -
    5. C:\_temp\_smtpTest>_mailrep_use.exe
    6. 194.67.23.20    +
    7. C:\_temp\_smtpTest>_mailrep_use.exe
    8. 194.67.23.20    +
    9. C:\_temp\_smtpTest>_mailrep_use.exe
    10. 194.67.23.20    +
    11. C:\_temp\_smtpTest>_mailrep_use.exe
    12. 194.67.23.20    +
    13. C:\_temp\_smtpTest>_mailrep_use.exe
    14. 194.67.23.20    +
    15. C:\_temp\_smtpTest>_mailrep_use.exe
    16. 194.67.23.20    -
    17. C:\_temp\_smtpTest>_mailrep_use.exe
    18. 194.67.23.20    +
    19. C:\_temp\_smtpTest>_mailrep_use.exe
    20. 194.67.23.20    -
    Запускаю 10 раз на ns4.mail.ru,
    то есть заведомо там порт 25 не открыт.

    Все разы отбой. Работает правильно.

    Чем меньше тайм-аут тем больше ошибок.

    Может можно быстрее проверить открыт ли порт 25 на заданном хосте?
     
  11. nester7

    nester7 New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2003
    Сообщения:
    720
    Адрес:
    Russia
    select() нужно в цикле гонять. Это не ошибки, скорее всего
    это просто предельное значение в твоем случае и пакетики
    не всегда укладываются в этот интервал.

    Быстрее, чем работает сеть или как? :)
    Я не понял вопроса.
    Вообще можно, конечено, если вспомнить что connect() - это три TCP-сегмента, а для
    проверки открыт ли порт, достаточно двух. Под windows видимо, можно сие сделать,
    используя библиотеку WinPcap; на *nix - через RAW_SOCKET'ы.
    Но насчёт сильного увеличения скорости я сильно сомневаюсь, ибо мне представляется,
    что connect(), возвращает управление при получении второго сегмента, но после того,
    как отработает код отправки третьего. На большом количестве сокетов это даст выигрыш,
    но на одном, по-моему, только зря время тратить на такаую реализацию.
     
  12. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    nester7
    select() нужно в цикле гонять
    это да, спасибо!
     
  13. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    Удивительное рядом!
    Сижу вечером запускаю эту функцию
    (ее последний вариант - смотри выше через пост) на smtp.mail.ru.
    Подклюситься на 25 порт не удается!

    Встаю утром и все получается! Чудеса!?
     
  14. Aspire

    Aspire New Member

    Публикаций:
    0
    Регистрация:
    19 май 2007
    Сообщения:
    1.028
    Как кто-то верно заметил, на smtp.mail.ru порт 2525, а не 25.