ftp и сокеты

Тема в разделе "WASM.NETWORKS", создана пользователем __Ranger, 23 ноя 2004.

  1. __Ranger

    __Ranger New Member

    Публикаций:
    0
    Регистрация:
    8 апр 2003
    Сообщения:
    23
    Адрес:
    Russia
    Постил вопрос на RSDN'e, но без особого упеха, может тут найдется знающий человек?



    Пишу программу, в которой требуется получиь список фйлов на фтп сервере. InternetOpen и прочее не подходит, т.к FtpFindNext не умеет отличать файл от линка на файл. Пишу сейчас через команды, но столкнулся с проблемой. Делаю USER, PASS, CWD, PORT, LIST - всё нормально, приходит список файлов. Пытаюсь закрыть сокет, который получил после Accept - возвращает WSAEINVAL :dntknw: Настоящий же сокет(который на listen поставлен) закрывается нормально. Сервер, видимо, ждет закрытия сокета, потому что после команды LIST другие не выполняет. Посмотрел через снифер другой фтп клиент - после LIST идут пакеты серверу по FTP-DATA ACK, RST, у меня же их программа не посылает. Где может быть косяк?


    Код (Text):
    1.  
    2. WndProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
    3.     mov     eax,uMsg
    4.     .if eax==WM_INITDIALOG
    5.         push    hWin
    6.         pop hWnd
    7.         and cmd_sock,0
    8.         and data_sock,0
    9.     .elseif eax==WM_COMMAND
    10.         mov     eax,wParam
    11.         and     eax,0FFFFh
    12.         .if eax == go_btn
    13.             invoke ftp_connect
    14.         .endif
    15.     .elseif eax==WM_CLOSE
    16.         invoke DestroyWindow,hWin
    17.     .elseif uMsg==WM_DESTROY
    18.         invoke PostQuitMessage,NULL
    19.     .else
    20.         invoke DefWindowProc,hWin,uMsg,wParam,lParam
    21.         ret
    22.     .endif
    23.     xor    eax,eax
    24.     ret
    25.  
    26. WndProc endp
    27.  
    28. create_listen_sock proc
    29.     LOCAL sin: sockaddr_in
    30.     LOCAL temp:DWORD
    31.       invoke socket, AF_INET, SOCK_STREAM, IPPROTO_TCP
    32.       mov data_sock,eax
    33.       mov sin.sin_port,0
    34.       mov sin.sin_family,AF_INET
    35.       mov sin.sin_addr,INADDR_ANY
    36.       invoke bind, data_sock, addr sin , sizeof(sockaddr_in)
    37.       invoke getsockname,data_sock,addr sin,addr temp;offset szSockaddr_in
    38.       xor eax,eax
    39.       mov ax,sin.sin_port
    40.       invoke ntohs,eax
    41.       invoke prep_port_cmd,eax ; тут готовится строка для PORT
    42.       invoke listen, data_sock, 1
    43.       ret
    44. create_listen_sock endp
    45.  
    46. ftp_connect proc uses ebx
    47.     LOCAL sin: sockaddr_in
    48.     LOCAL buff[255]:BYTE
    49.     LOCAL buff2[255]:BYTE
    50.     invoke SendDlgItemMessage,hWnd,serv_list,WM_GETTEXT,255,addr buff2
    51.     INVOKE inet_addr,addr buff2
    52.     .IF eax==INADDR_NONE
    53.         INVOKE gethostbyname, addr buff2
    54.         .if eax == 0
    55.             jmp err
    56.         .endif
    57.         mov  eax,dword ptr [eax+12]
    58.         mov  eax,dword ptr [eax]
    59.         mov  eax,dword ptr [eax]
    60.         mov sin.sin_addr,eax
    61.     .ELSE
    62.         mov sin.sin_addr,eax
    63.     .ENDIF     
    64.     mov     sin.sin_port,1500h
    65.     mov     sin.sin_family,AF_INET
    66.     mov     sin.sin_addr,eax
    67.     invoke lstrcpy, offset cur_path, offset cwd_cmd
    68.     invoke socket, AF_INET, SOCK_STREAM, IPPROTO_TCP
    69.     mov cmd_sock,eax
    70.     ;invoke    WSAAsyncSelect, cmd_sock, hWnd, WM_COMMANDSOCK,FD_READ+FD_CONNECT
    71.     pd eax,"SELECT"
    72.     invoke connect,cmd_sock,addr sin,sizeof(sockaddr_in)
    73.     invoke recv,cmd_sock,cmd_buff,10000,0
    74.     invoke send_command,offset user_cmd
    75.     invoke recv,cmd_sock,cmd_buff,10000,0
    76.     invoke send_command,offset pass_cmd
    77.     invoke recv,cmd_sock,cmd_buff,10000,0
    78.     invoke send_command,offset cwd_cmd
    79.     invoke recv,cmd_sock,cmd_buff,10000,0
    80.     invoke CreateListenSock
    81.     invoke send_command,offset port_cmd
    82.     invoke recv,cmd_sock,cmd_buff,10000,0
    83.     invoke send_command,offset list_cmd
    84.     invoke recv,cmd_sock,cmd_buff,10000,0
    85.     invoke accept,data_sock,0,0;addr data_buff,1000;sizeof(sockaddr_in)
    86.     mov real_data_sock,eax
    87.     mov ebx,data_buff
    88. next_data:
    89.     invoke recv,real_data_sock,ebx,50000,0
    90.     add ebx,eax
    91.     test eax,eax
    92.     jz next_data
    93.       ;получаю список файлов
    94.     sub ebx,data_buff
    95.     mov ftp_data_size,ebx
    96.     invoke closesocket,real_data_sock
    97.     ; тут -1
    98.     invoke WSAGetLastError
    99.     ; тут WSAENVAL(10022)
    100.     invoke closesocket,data_sock
    101.     ; этот нормально закрывается
    102.    
    103. err:
    104.     ret
    105. ftp_connect endp
    106.  
    107.  
     
  2. StoneColdCrazy

    StoneColdCrazy New Member

    Публикаций:
    0
    Регистрация:
    28 окт 2004
    Сообщения:
    18
    Завершай сеанс командой QUIT перед закрытием сокета.
     
  3. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
    Вот сходи на http://www.protocols.ru/ "Библиотека сетевых протоколов" там есть русифицированные RFC
     
  4. __Ranger

    __Ranger New Member

    Публикаций:
    0
    Регистрация:
    8 апр 2003
    Сообщения:
    23
    Адрес:
    Russia
    >>Завершай сеанс командой QUIT перед закрытием сокета.

    Дык мне нужно не соединение с сервером закрыть, а канал данных. Он ждет пакета RST, после чего шлет мне по управляющему соединению что-нибудь вроде "200 Transfer Complete". Этот пакет видимо должен уходить после closesocket, но почему-то мастдай не даёт мне закрыть сокет.



    RFC'ы я читал, косяк не в командах, а в моей реализации под винду.
     
  5. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    __Ranger

    После приёма списка файлов, перед закрытием соединения, отправь в real_data_sock один байт.
     
  6. __Ranger

    __Ranger New Member

    Публикаций:
    0
    Регистрация:
    8 апр 2003
    Сообщения:
    23
    Адрес:
    Russia
    Блин, где ты раньше был? :dntknw:( Уже всё переписал под пассивный режим, там без проблем. Но всё равно спасибо.



    Раз уж пошла такая пьянка,ещё такой вопрос. При коннекте (connect) на неотвечающий хост есть некий таймаут, после которого и синронный и асинхронный сокеты вываливаются с -1. Так вот, как можно изменить значение этого таймаута? Пробовал setsockopt(SO_RCVTIMEO) ошибки не возвращает, но и ничего не делает. Может это значение где-нить в реестре хранится? Можно, конечно, повесить это дело в отдельный тред и по собственному таймауту его убивать, но в MS так не советуют делать.
     
  7. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    MSDN:



    BSD options not supported for setsockopt are:



    SO_RCVTIMEO int Receives time-out (available in Microsoft implementation of Windows Sockets 2).




    То есть для установки данной опции нужно в WSAStartup вторую версию запросить.