привет. сейчас пишу http клиента. цель программы - получить html код странички. впринципе, все сделано, но у меня есть 1 вопрос. пишу в среде fasm под винду. есть код получения данных с http сервера в цикле и последующая отправка этих данных на форму: Код (Text): .recvdataloop: invoke recv,ebx,buf1,512,0 mov edi, eax invoke lstrcat, msgText,buf1 test edi, edi jg .recvdataloop так вот, получение данных происходит ОЧЕНЬ долго.. задерживает именно цикл, в это время форма зависает. проходит секунд 15 и данные успешно копируются в окно программы с помощью SetWindowText вопрос: почему так долго происходит получение данных (долгая работа цикла)? делал аналогичный пример на языке си в консольном приложении - моментально все происходит и выводится в окно cmd.exe... ломаю голову над примером на асме.. помогите, пожалуйста, решить проблему
Си-вариант: Код (Text): #include <winsock2.h> #include <windows.h> #include <stdio.h> #pragma comment(lib, "ws2_32") #define DEFAULT_BUFLEN 512 int main(int argc, char*argv[]) { WSADATA wsaData; int iResult; SOCKET ConnectSocket; struct sockaddr_in clientService; char *sendbuf = "GET / HTTP/1.1\r\nHost:www.liveinternet.ru\r\nUser-Agent: Internet Explorer\r\n\r\n"; char recvbuf[DEFAULT_BUFLEN]; int recvbuflen = DEFAULT_BUFLEN; iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != NO_ERROR) { printf("WSAStartup failed: %d\n", iResult); return 1; } ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (ConnectSocket == INVALID_SOCKET) { printf("Error at socket(): %ld\n", WSAGetLastError() ); WSACleanup(); return 1; } clientService.sin_family = AF_INET; clientService.sin_addr.s_addr = inet_addr( "88.212.196.87" ); // айпи liveinternet.ru clientService.sin_port = htons(80); iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) ); if ( iResult == SOCKET_ERROR) { closesocket (ConnectSocket); printf("Unable to connect to server: %ld\n", WSAGetLastError()); WSACleanup(); return 1; } iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 ); if (iResult == SOCKET_ERROR) { printf("send failed: %d\n", WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } iResult = shutdown(ConnectSocket, SD_SEND); if (iResult == SOCKET_ERROR) { printf("shutdown failed: %d\n", WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } do { iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); printf("%s",recvbuf); } while( iResult > 0 ); closesocket(ConnectSocket); WSACleanup(); return 0; } ASM вариант в аттаче (сорцы+exe)
s0lidude > аналогичный пример на языке си Не совсем аналогичный. Например: 1) разные параметры вызова socket Си: socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /* (2, 1, 6)*/ Asm: invoke socket, 2, 1, 0 2) настройка сокета Си: shutdown(ConnectSocket, SD_SEND); Asm: - 3) размер буфера приемника Си: 512 Asm: 4096 4) вывод на экран Си: по мере поступления Asm: после полного получения.
lstrcat добавляет в конец строки с завершающим нулём строку с завершающим нулём. С чего ты взял, что recv положит в buf1 именно такую строку? Добавляй ноль сам в [buf1+eax], предварительно проверив edi на -1, или получай данные прямо в нужное место msgText (mov esi, msgText; invoke recv ebx,esi,4096,0; (после проверки) add esi,eax).
Не лучще в подобных случиях юзать функции wininet ? Код (Text): @@: mov bytewrite,0 invoke RtlZeroMemory,addr buffer,sizeof buffer invoke InternetReadFile,hRequest,addr buffer,sizeof buffer,addr bytewrite .if eax != 0 && bytewrite != 0 jmp @B .endif
Оффтоп: Flasher, велосипеды изобретать обязательно (чтобы понять, как они работают), но не обязательно их использовать
q_q, это не имеет принципиального значения. я пробовал все это подставлять. iZzz32, причем тут lstrcat? попробуй удалить ее из цикла и просто оставить получение данных и проверку, все равно будет долго происходить. Кто-нить пробовал запускать это? Flasher, у меня нет проблем с получением данных, поэтому зачем мне альтернативы? У меня проблема в том, что получение просто затягивается, хотя если смотреть через откладчик, к примеру, то данные приходят мгновенно, а без отладчика - долго..
s0lidude, тебе нужно было в асм коде заюзать функцию shutdown, прежде чем получать поток данных. т.к. shutdown закрывает открытый сокет, давая тем самым получить данные до конца. поэтому после того, как данных уже не будет, recv не будет ждать и сразу вернет управление. на крайняк, нужно задавать таймаут ожидания