connect -> WSAENOTSOCK

Тема в разделе "WASM.NETWORKS", создана пользователем mc black, 29 май 2010.

  1. mc black

    mc black Member

    Публикаций:
    0
    Регистрация:
    19 янв 2005
    Сообщения:
    213
    Адрес:
    Russia, N.Novgorod
    Уважаемые форумчане! Не могу самостоятельно разобраться с ошибкой WSAENOTSOCK "The descriptor is not a socket", которая возникает при подключении connect, причем сокет создается без ошибки, а ошибка вылезает во время подключения (смотрю в отладчике OllyDebug 2.00k)? Просмотрел все 10 раз, в упор не вижу, где я накосячил.
    Код (Text):
    1. .386
    2. .model flat, stdcall
    3. option casemap :none
    4.  
    5. include windows.inc
    6. include kernel32.inc
    7. include wsock32.inc
    8.  
    9. includelib kernel32.lib
    10. includelib wsock32.lib
    11.    
    12. .data
    13.    
    14.     szHostname db "www.ya.ru",0
    15.     http_request db "GET / HTTP/1.1",13,10,\
    16.     "Host: www.nntt.org",13,10,\
    17.     "User-Agent: socket-c",13,10,13,10,0
    18.    
    19. .code
    20.  
    21. socket_c proc
    22.     LOCAL wsa:WSADATA
    23.     LOCAL ip:DWORD
    24.     LOCAL sock:DWORD
    25.     LOCAL sadr:sockaddr_in
    26.    
    27.     invoke WSAStartup,202h,addr wsa
    28.     test eax,eax
    29.     jnz exitproc
    30.    
    31.     invoke gethostbyname,addr szHostname
    32.     test eax,eax
    33.     jz cleanup
    34.     assume eax:ptr hostent
    35.     mov eax,[eax].h_list
    36.     mov eax,dword ptr [eax]
    37.     mov eax,dword ptr [eax]
    38.     mov ip,eax
    39.    
    40.     invoke socket,AF_INET,SOCK_STREAM,0
    41.     test eax,SOCKET_ERROR
    42.     jz cleanup
    43.    
    44.     mov sadr.sin_family,AF_INET
    45.     invoke htons,80
    46.     mov sadr.sin_port,80
    47.     mov eax,ip
    48.     mov sadr.sin_addr,eax
    49.     invoke RtlZeroMemory,addr sadr.sin_zero,8
    50.     invoke connect,sock,addr sadr,sizeof sadr
    51.     test eax,eax
    52.     jnz cleansock
    53.    
    54.     invoke send,sock,addr http_request,sizeof http_request,0
    55.     test eax,SOCKET_ERROR
    56.     jz cleansock
    57.    
    58. cleansock:
    59.     invoke closesocket,sock
    60. cleanup:
    61.     invoke WSACleanup
    62. exitproc:
    63.     ret
    64. socket_c endp
    65.  
    66. start:
    67.    
    68.     invoke socket_c
    69.     invoke ExitProcess,0
    70.    
    71. end start
    Код выкладываю целиком и как есть - дальше send ничего еще не написано. Цель, как несложно понять, соединиться с web-сервером и получить содержание главной страницы сайта. Осваиваю сокеты, переписывая пример с VB6 на ASM.
     
  2. mc black

    mc black Member

    Публикаций:
    0
    Регистрация:
    19 янв 2005
    Сообщения:
    213
    Адрес:
    Russia, N.Novgorod
    Нашел свою ошибку, самую тупую, какие только бывают. Забыл сохранить дескриптор сокета в переменную, которую затем использовал при подключении. В упор не видел эту ошибку до тех пор, пока не увидел в отладчике, что для connect в стек вместо нормального дескриптора сокета передавался всякий мусор из стека. Чтобы исправить, дописал одну строку: mov sock,eax после проверки на ошибку функции socket.

    Правда осталась ошибка WSAETIMEDOUT при работе в отладчике, но это похоже как раз задержка работы отладчика, в нормальном режиме этого быть не должно. Всем спасибо за внимание!
     
  3. litrovith

    litrovith Member

    Публикаций:
    0
    Регистрация:
    20 июн 2007
    Сообщения:
    509
    Код (Text):
    1. ..............
    2.     invoke socket,AF_INET,SOCK_STREAM,0
    3.     test eax,SOCKET_ERROR
    4.     jz cleanup
    5.     mov sock, eax  ; <<<<<<<<<<<<<<<<
    6.  
    7.     mov sadr.sin_family,AF_INET
    8. ..................
     
  4. mc black

    mc black Member

    Публикаций:
    0
    Регистрация:
    19 янв 2005
    Сообщения:
    213
    Адрес:
    Russia, N.Novgorod
    Да, все верно. Есть еще пара несуразностей в моем исходнике: указано разное имя хоста для тестирования программы, надо обращаться к одному хосту по имени, вот так:
    Код (Text):
    1. .data
    2.    
    3.     szHostname db "www.ya.ru",0
    4.     http_request db "GET / HTTP/1.1",13,10,\
    5.     "Host: www.ya.org",13,10,\                 ;<<<<<<<<<<<<<
    6.     "User-Agent: socket-c",13,10,13,10,0
    И ещё одна ерунда, появившаяся во время моей "отладки". Порт в connect передаем в сетевом порядке байт, т.е. как результат htons в ax:
    Код (Text):
    1.     mov sadr.sin_family,AF_INET
    2.     invoke htons,80
    3.     mov sadr.sin_port,ax     ;<<<<<<<<<<<<<<<<<<<<
    4.     mov eax,ip
    5.     mov sadr.sin_addr,eax
    6.     invoke RtlZeroMemory,addr sadr.sin_zero,8
    7.     invoke connect,sock,addr sadr,sizeof sadr
    8.     test eax,eax
    9.     jnz cleansock
    Если доведу пример http-downloader'а до ума, выложу готовый исходник.