Как с помощью seleck() оборвать затянувшийся connect()?

Тема в разделе "WASM.BEGINNERS", создана пользователем _animaTOR_, 7 июн 2007.

  1. _animaTOR_

    _animaTOR_ New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    58
    Сел писать код, который конектится к smtp по заданному его ip, а в случае напал на ip c закрытым 25 портом хочу быстро отпасть.

    Для этого использовал функцию select(), заполнил структуры ... вот код ...
    Вход - стока с ip - адресом --> _strIP
    Выход - (0) если сервер ответил строкой "220 ..." и (-1) если сервер не вернул строку с "220 ... ".
    Код (Text):
    1.     invoke  WSAStartup,101h,offset wsadata
    2.     invoke  socket,AF_INET,SOCK_STREAM,0
    3.     .if eax != INVALID_SOCKET
    4.         mov sock,eax
    5.         mov s_addr.sin_family,AF_INET
    6.         invoke  htons,25
    7.         mov s_addr.sin_port,ax
    8.         invoke  inet_addr,[_strIP]
    9.         mov s_addr.sin_addr,eax
    10. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    11.         xor edx, edx
    12.         mov time_out.tv_sec, 0
    13.         mov time_out.tv_usec, 500
    14.         mov dword ptr [fds.fd_count], 1
    15.         push    sock
    16.         pop fds.fd_array
    17.         invoke  select, 0, ADDR fds, ADDR fds, 0, ADDR time_out ; Ждем (500 ms)
    18.         .if eax != INVALID_SOCKET
    19.             invoke  connect,sock,addr s_addr,sizeof s_addr
    20.             .if eax != INVALID_SOCKET
    21.                 invoke  recvfrom, sock, ADDR r_buf, 512, 0, addr s_addr, sizeof s_addr
    22.                 cmp dword ptr [r_buf],' 022'
    23.                 jz  ___quit0
    24.             .endif
    25.         .endif
    26.     .endif
    27. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    28. ___quit1:
    29.     invoke  closesocket,sock
    30.     invoke  WSACleanup
    31.     xor eax,eax
    32.     mov eax,-1
    33.     ret
    34. ___quit0:
    35.     invoke  closesocket,sock
    36.     invoke  WSACleanup
    37.     xor eax,eax
    38.     ret
    Если _strIP - адрес реального smtp - сервера, то результат приходит быстро.
    Если _strIP - адрес не smtp - сервер, то результат приходится ждать долго. Но я же в задержке задал конкретный (короткий) интервал?

    Мне кажется что я неправильно применяю эту функцию select().

    Поясните, пожалуйста, что делать чтобы не все-таки 500ms ждать результат выполнения connect().
     
  2. Mental_Mirror

    Mental_Mirror New Member

    Публикаций:
    0
    Регистрация:
    7 май 2007
    Сообщения:
    431
    В твоем случае select не подходит. Там есть только один связанный с этим событием набор - writefds - но только при неблокирующем вызове соединения. Поэтому используй неблокирующий режим работы сокетов. Сокет можно привести в неблокирующий режим так -
    Код (Text):
    1. .data?
    2. Num dd 1
    3. ...
    4. invoke ioctlsocket,socket,FIOBIO,offset Num
     
  3. _animaTOR_

    _animaTOR_ New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    58
    Mental_Mirror
    тоесть выбросить этот select() ... и сделать следующее ...
    Код (Text):
    1. .data?
    2. Num dd 1
    3.     .
    4.     .
    5.     .
    6.     invoke  WSAStartup,101h,offset wsadata
    7.     invoke  socket,AF_INET,SOCK_STREAM,0
    8.     .if eax != INVALID_SOCKET
    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,[_strIP]
    14.         mov s_addr.sin_addr,eax
    15. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    16.        
    17.         invoke ioctlsocket,socket,FIOBIO,offset Num ; <------------!!!
    18.        
    19.         .if eax != INVALID_SOCKET
    20.             invoke  connect,sock,addr s_addr,sizeof s_addr
    21.             .if eax != INVALID_SOCKET
    22.                 invoke  recvfrom, sock, ADDR r_buf, 512, 0, addr s_addr, sizeof s_addr
    23.                 cmp dword ptr [r_buf],' 022'
    24.                 jz  ___quit0
    25.             .endif
    26.         .endif
    27.     .endif
    28. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    29. ___quit1:
    30.     invoke  closesocket,sock
    31.     invoke  WSACleanup
    32.     xor eax,eax
    33.     mov eax,-1
    34.     ret
    35. ___quit0:
    36.     invoke  closesocket,sock
    37.     invoke  WSACleanup
    38.     xor eax,eax
    39.     ret
     
  4. Mental_Mirror

    Mental_Mirror New Member

    Публикаций:
    0
    Регистрация:
    7 май 2007
    Сообщения:
    431
    _animaTOR_
    Теперь просто connect сразу вернет управление со статусом - "в процессе". Следующие вызовы connect могут вернуть успех, либо опять же "в процессе". Теперь select просто будет работать на событии об успешном соединении и connect не будет тормозить, т.к. он сразу будет возвращаться. Т.о. select просто не работает на блокирующем сокете. Ну это можно почитать в SDK.