Добрый день! Проверяю заданный IP - на открытый 25 порт. Пишу функцию - на вход подаю интерес. IP - на выходе 0 - порт 25 открыт -1 - порт 25 закрыт Код (Text): _smtptest proc _strIP:DWORD LOCAL _strIP_ [50]:BYTE LOCAl time_out : timeval LOCAL fds : fd_set invoke lstrcpy,ADDR _strIP_, [_strIP] invoke WSAStartup,101h,offset wsadata invoke socket,AF_INET,SOCK_STREAM,0 mov sock,eax mov s_addr.sin_family,AF_INET invoke htons,25 mov s_addr.sin_port,ax invoke inet_addr,ADDR _strIP_ mov s_addr.sin_addr,eax invoke connect,sock,addr s_addr,sizeof s_addr ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; xor edx, edx mov time_out.tv_sec, 1 ; структура, определяющая, сколько mov time_out.tv_usec, 500 ; времени select будет ждать окончания ; ввода-вывода mov dword ptr [fds.fd_count], 1 push sock pop fds.fd_array invoke select, 0, ADDR fds, edx, edx, ADDR time_out ; Ждем 500 ms test eax, eax ; Если данные не поступили jz ___quit1 ; то переходим ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; invoke recvfrom, sock, ADDR r_buf, 512, 0, addr s_addr, sizeof s_addr cmp dword ptr [r_buf],' 022' jz ___quit0 ___quit1: invoke closesocket,sock invoke WSACleanup xor eax,eax mov eax,-1 ; 25 - закрыт ret ___quit0: invoke closesocket,sock invoke WSACleanup xor eax,eax ; 25 - открыт ret ;------------------------------------ ;------------------------------------ _smtptest endp Подставляю IP - 194.67.23.20 - Это smtp.mail.ru Проверил : Код (Text): c:/> telnet 194.67.23.20 220 Mail.Ru ESMTP . . . то есть 25 порт открыт. А у меня он закрыт получаестя ( Может я неправильно пользуюсь функцией select()? Вроде как все делаю по книге Йон Снейдеp "Эффективное пpогpаммиpование TCP/IP". 25-совет использование select().
1. если коннект прошел успешно (invoke connect,sock,addr s_addr,sizeof s_addr), значит порт открыт. Где проверка на успешность? 2. WSAGetLastError() что говорит после твоего селекта? а вообще: Код (Text): _smtptest proc _strIP:DWORD LOCAL _strIP_ [50]:BYTE invoke lstrcpy,ADDR _strIP_, [_strIP] invoke WSAStartup,101h,offset wsadata invoke socket,AF_INET,SOCK_STREAM,0 mov sock,eax mov s_addr.sin_family,AF_INET invoke htons,25 mov s_addr.sin_port,ax invoke inet_addr,ADDR _strIP_ mov s_addr.sin_addr,eax invoke connect,sock,addr s_addr,sizeof s_addr ret _smtptest endp
select используется не для "проверки открыт ли порт", а для опроса массива сокетов на предмет их готовности для операций синхронного ввода-вывода. На первый взгляд в коде боков вроде нету, так что дебаггер те в руки и вперед... И вообще, походу, recvfrom здесь для твоей задачи избыточен. Если select вернул не ноль, то ответ пришел, прыгай сразу на quit0.
nester7 да я вообще-то с этим select - том вожусь чтоб как-то ускорить работу функции с "неправильными" ip. Но кажется что с select() что без него "неправильные" ip где-то секунду так и обрабатываются. dimonn > для опроса массива сокетов на предмет их готовности для операций синхронного ввода-вывода вот я же и добавил его в массив, и проверяю на предмет готовности к вводу-выводу Код (Text): ... mov dword ptr [fds.fd_count], 1 push sock pop fds.fd_array ... > вообще, походу, recvfrom здесь для твоей задачи избыточен. да, верно, спасибо. Я просто эту проверку для пущей уверенности поставил
_sheva740 Что значит неправильные IP? Не существующие чтоли? Так они по другому определяются. Пингом например. А селект для проверки открытых портов совсем незачем. Или тебе всё же данные надо получать? Тогда можно. nester7 Зачем неблокируемые сокеты? Время cpu кушать?
nester7 Нашел У. Р. Стивенс ...UNIX. Разработка сетевых приложений Читал избарательно. Приведу выдержки - Глава 13.2 - Тайм - ауты сокета Раздел Тайм - аут для функции connect(). [...] Функцию selest() можно использовать для установки тайм-аута функции connect(), только когда сокет находится в неблокируемом режиме [...] Листинг 13.3. Функция readable_timeo: ожидание, когда дескриптор станет готов для чтения Код (Text): //lib/readable_timeo.с #include "imp.h" int readable_timeo(int fd, int sec) { fd_set rset; struct timeval tv; FD_ZERO(&rset); FD_SET(fd, &rset); tv.tv_sec =sec; tv.tv_usec =0; return (select(fd + 1, &rset, NULL, NULL, &tv)); } Все как бы делаю правильно. Поэтому исправил свою функцию : Код (Text): _smtptest proc _strIP:DWORD LOCAL _strIP_ [50]:BYTE LOCAl time_out : timeval LOCAL fds : fd_set LOCAL dwZero : DWORD invoke lstrcpy,ADDR _strIP_, [_strIP] invoke WSAStartup,202h,offset wsadata invoke socket,AF_INET,SOCK_STREAM,0 mov sock,eax ;------------------------------------ mov dwZero,1 invoke ioctlsocket, sock, FIONBIO, ADDR dwZero ;------------------------------------ mov s_addr.sin_family,AF_INET invoke htons,25 mov s_addr.sin_port,ax invoke inet_addr,ADDR _strIP_ mov s_addr.sin_addr,eax invoke connect,sock,addr s_addr,sizeof s_addr xor edx, edx mov time_out.tv_sec, 1;1 ; структура, определяющая, сколько mov time_out.tv_usec, 0;500 ; времени select будет ждать окончания ; ввода-вывода mov dword ptr [fds.fd_count], 1 push sock pop fds.fd_array invoke select, 0, ADDR fds, edx, edx, ADDR time_out ; Ждем 1s cmp eax, 1 ; Если select() вернул 1 ; - значит один сокет готов к работе je ___quit0 ; то переходим на +OK ___quit1: invoke closesocket,sock xor eax,eax mov eax,-1 ret ___quit0: invoke closesocket,sock xor eax,eax ret _smtptest endp Запускаю 10 раз на smtp.mail.ru Код (Text): C:\_temp\_smtpTest>_mailrep_use.exe 194.67.23.20 - C:\_temp\_smtpTest>_mailrep_use.exe 194.67.23.20 - C:\_temp\_smtpTest>_mailrep_use.exe 194.67.23.20 + C:\_temp\_smtpTest>_mailrep_use.exe 194.67.23.20 + C:\_temp\_smtpTest>_mailrep_use.exe 194.67.23.20 + C:\_temp\_smtpTest>_mailrep_use.exe 194.67.23.20 + C:\_temp\_smtpTest>_mailrep_use.exe 194.67.23.20 + C:\_temp\_smtpTest>_mailrep_use.exe 194.67.23.20 - C:\_temp\_smtpTest>_mailrep_use.exe 194.67.23.20 + C:\_temp\_smtpTest>_mailrep_use.exe 194.67.23.20 - Запускаю 10 раз на ns4.mail.ru, то есть заведомо там порт 25 не открыт. Все разы отбой. Работает правильно. Чем меньше тайм-аут тем больше ошибок. Может можно быстрее проверить открыт ли порт 25 на заданном хосте?
select() нужно в цикле гонять. Это не ошибки, скорее всего это просто предельное значение в твоем случае и пакетики не всегда укладываются в этот интервал. Быстрее, чем работает сеть или как? Я не понял вопроса. Вообще можно, конечено, если вспомнить что connect() - это три TCP-сегмента, а для проверки открыт ли порт, достаточно двух. Под windows видимо, можно сие сделать, используя библиотеку WinPcap; на *nix - через RAW_SOCKET'ы. Но насчёт сильного увеличения скорости я сильно сомневаюсь, ибо мне представляется, что connect(), возвращает управление при получении второго сегмента, но после того, как отработает код отправки третьего. На большом количестве сокетов это даст выигрыш, но на одном, по-моему, только зря время тратить на такаую реализацию.
Удивительное рядом! Сижу вечером запускаю эту функцию (ее последний вариант - смотри выше через пост) на smtp.mail.ru. Подклюситься на 25 порт не удается! Встаю утром и все получается! Чудеса!?