Вопрос по размеру буфера в ReadConsole и WriteConsole

Тема в разделе "WASM.BEGINNERS", создана пользователем Alexander_N, 1 авг 2008.

  1. Alexander_N

    Alexander_N New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2008
    Сообщения:
    16
    Подскажите пожайлуста! Имеется консольная программа на Фасме, котороя слушает заданный порт. При установке соединения предоставляет пользователю консоль для общения с собеседником.

    Я определил два буфера для приема и для передачи данных (send и recv), эти же буфера я использую для чтения и записи в консоль (ReadConsole и WriteConsole).

    Вопрос такой: правильно ли я определяю размеры помещенных в буфере данных (они потом передаются параметром в вызванных АПИ)? И как сделать, что-бы вводились и выводились данные без мусора т.е как правильно определить кол-во символов в буфере? Листинг ниже.
     
  2. Alexander_N

    Alexander_N New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2008
    Сообщения:
    16
    format PE console 4.0
    entry start
    include 'win32a.inc'
    section '.udata' readable writeable
    wsadata WSADATA
    sa sockaddr_in
    sizesa = $-sa
    hSock dd ?
    hOutPut dd ?
    hInput dd ?
    nWriten dd ?
    nRead dd ?
    section '.data' data readable writeable
    ip db "192.168.1.2",0
    consoletitle db "Connecting with client",0
    Msg1 db "CLIENT <<<<<",0
    Msg2 db "SERVER >>>>>",0
    net_buff_recv db 20000 dup (?)
    net_buff_recv_sz = $-net_buff_recv
    net_buff_send db 20000 dup (?)
    net_buff_send_sz = $-net_buff_send
    section '.code' code readable executable
    start:
    invoke SetConsoleTitle, consoletitle
    invoke WSAStartup, 0202h, wsadata
    or eax,eax
    jnz Exit
    mov [sa.sin_family],AF_INET

    invoke inet_addr,ip
    mov [sa.sin_addr],eax

    invoke htons,999
    mov [sa.sin_port],ax

    invoke socket,AF_INET,SOCK_STREAM,0
    mov esi,eax

    invoke bind,esi,sa,sizesa
    or eax,eax
    jnz cs1

    invoke listen,esi,1
    or eax,eax
    jnz cs1
    mov eax,sizesa
    lea edi,[hSock]
    mov [edi],eax

    invoke accept,esi,[sa],[hSock]
    or eax,eax
    jz cs2
    mov [hSock], eax


    ;получаем хэндл для ввода
    invoke GetStdHandle,STD_INPUT_HANDLE
    mov [hInput], eax

    ;получаем хэндл для вывода
    invoke GetStdHandle, STD_OUTPUT_HANDLE
    mov [hOutPut], eax

    read_loop:
    ;печатаем "CLIENT <<<<< "
    invoke WriteConsole, [hOutPut],Msg1, 12, nWriten, NULL
    or eax,eax
    jz cs2
    ;вводим команду клиенту
    invoke ReadConsole, [hInput], net_buff_send, net_buff_send_sz, nRead, NULL
    or eax,eax
    jz cs2
    ;отсылаем данные по сети
    invoke send, hSock, net_buff_send, net_buff_send_sz, 0

    ;принимаем данные из сети
    invoke recv, hSock, net_buff_recv, net_buff_recv_sz,0

    ;печатаем "SERVER >>>>>"
    invoke WriteConsole, [hOutPut], Msg2, 12, nWriten, NULL
    or eax,eax
    jz cs2
    ;вывод на экран ответа клиента
    invoke WriteConsole, [hOutPut], net_buff_recv, net_buff_recv_sz, nWriten, NULL
    or eax,eax
    jz cs2
    jmp read_loop
    cs2:
    invoke closesocket,hSock
    cs1:
    invoke closesocket,esi
    wsa:
    invoke WSACleanup

    Exit:
    invoke ExitProcess,0

    section '.idata' import data readable writeable

    library kernel,'KERNEL32.DLL',\
    winsock,'ws2_32.DLL'

    import kernel,\
    SetConsoleTitle,'SetConsoleTitleA',\
    WriteConsole,'WriteConsoleA',\
    ReadConsole,'ReadConsoleA',\
    GetStdHandle,'GetStdHandle',\
    ExitProcess,'ExitProcess'


    import winsock,\
    WSAStartup,'WSAStartup',\
    inet_addr,'inet_addr',\
    htons,'htons',\
    WSACleanup,'WSACleanup',\
    socket,'socket',\
    bind,'bind',\
    listen,'listen',\
    accept,'accept',\
    recv,'recv',\
    send,'send',\
    closesocket,'closesocket'
     
  3. Alexander_N

    Alexander_N New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2008
    Сообщения:
    16
    Так, что никто не знает? Подскажите, пожайлуста уже второй день сижу никак разобраться не могу.
     
  4. n0hack

    n0hack New Member

    Публикаций:
    0
    Регистрация:
    3 июн 2008
    Сообщения:
    71
    Во-первых
    Код (Text):
    1. net_buff_send db 20000 dup (?)
    ReadConsole больше 256-и символов читать не умеет.
    Размер считанных данных помещается в nRead, притом nRead должен быть >= 2, и последние два байта в буфере будут 00Dh, 00Ah.
    то есть делаешь примерно так:
    call ReadConsole
    test eax, eax
    jz @error
    sub nRead, 2 ; отсекаем лишние два символа
    jb @error ; sub устанавливает флаги в точности, как cmp
    push 0
    push nRead
    push net_buff_send
    push hSock
    call send ; отправляем nRead байт

    Еще хочу обратить внимание на то, что 1) send может послать меньше nRead байт => нужно вызывать эту функцию в цикле 2) если сокет не готов к чтению/записи, send/recv приведут к зависанию твоего приложения на неопределенное время => необходимо проверять состояние сокета с помощью select и ввести какой-нибудь таймаут (секунд 30), по истечении которого соединение закрывается в случае, если сокет все это время не готов для передачи данных.


    На последок - используйте, пожалуйста, тэг [ code] и не ждите скорых ответов в выходные :).
     
  5. Alexander_N

    Alexander_N New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2008
    Сообщения:
    16
    Спасибо!
     
  6. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    n0hack
    ReadConsole больше 256-и символов читать не умеет.
    Источник информации?
     
  7. n0hack

    n0hack New Member

    Публикаций:
    0
    Регистрация:
    3 июн 2008
    Сообщения:
    71
    q_q
    Источник: http://www.wasm.ru/forum/viewtopic.php?id=27873
    Мб я не совсем прав - считает то он ровно столько, сколько нужно, просто пользователь больше 256-и байт за один раз не введет.
     
  8. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    n0hack
    В той ветке нет упоминания о ReadConsole. Согласно msdn/psdk предел 64K.
     
  9. Alexander_N

    Alexander_N New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2008
    Сообщения:
    16
    Все в принципе получилось. Только вот такой вопрос. После того как принятые данные были получены, указатель для ввода оказывается сразу за принятыми данными. Как его переместить на новую строку?