Подскажите пожайлуста! Имеется консольная программа на Фасме, котороя слушает заданный порт. При установке соединения предоставляет пользователю консоль для общения с собеседником. Я определил два буфера для приема и для передачи данных (send и recv), эти же буфера я использую для чтения и записи в консоль (ReadConsole и WriteConsole). Вопрос такой: правильно ли я определяю размеры помещенных в буфере данных (они потом передаются параметром в вызванных АПИ)? И как сделать, что-бы вводились и выводились данные без мусора т.е как правильно определить кол-во символов в буфере? Листинг ниже.
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'
Во-первых Код (Text): 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] и не ждите скорых ответов в выходные .
q_q Источник: http://www.wasm.ru/forum/viewtopic.php?id=27873 Мб я не совсем прав - считает то он ровно столько, сколько нужно, просто пользователь больше 256-и байт за один раз не введет.
Все в принципе получилось. Только вот такой вопрос. После того как принятые данные были получены, указатель для ввода оказывается сразу за принятыми данными. Как его переместить на новую строку?