Цикл обработки recv

Тема в разделе "WASM.ASSEMBLER", создана пользователем s0lidude, 12 апр 2009.

  1. s0lidude

    s0lidude New Member

    Публикаций:
    0
    Регистрация:
    23 мар 2009
    Сообщения:
    14
    Адрес:
    ru
    привет.

    сейчас пишу http клиента. цель программы - получить html код странички. впринципе, все сделано, но у меня есть 1 вопрос.
    пишу в среде fasm под винду.

    есть код получения данных с http сервера в цикле и последующая отправка этих данных на форму:

    Код (Text):
    1.        
    2. .recvdataloop:
    3. invoke recv,ebx,buf1,512,0
    4. mov edi, eax
    5. invoke lstrcat, msgText,buf1
    6. test edi, edi
    7. jg .recvdataloop
    так вот, получение данных происходит ОЧЕНЬ долго.. задерживает именно цикл, в это время форма зависает. проходит секунд 15 и данные успешно копируются в окно программы с помощью SetWindowText

    вопрос: почему так долго происходит получение данных (долгая работа цикла)?

    делал аналогичный пример на языке си в консольном приложении - моментально все происходит и выводится в окно cmd.exe... ломаю голову над примером на асме..

    помогите, пожалуйста, решить проблему
     
  2. deLight

    deLight New Member

    Публикаций:
    0
    Регистрация:
    26 май 2008
    Сообщения:
    879
    выкладывай полный код, с и asm-версию
     
  3. s0lidude

    s0lidude New Member

    Публикаций:
    0
    Регистрация:
    23 мар 2009
    Сообщения:
    14
    Адрес:
    ru
    Си-вариант:
    Код (Text):
    1. #include <winsock2.h>
    2. #include <windows.h>
    3. #include <stdio.h>
    4.  
    5. #pragma comment(lib, "ws2_32")
    6. #define DEFAULT_BUFLEN 512
    7.  
    8. int main(int argc, char*argv[]) {
    9.     WSADATA wsaData;
    10.     int iResult;
    11.  
    12.     SOCKET ConnectSocket;
    13.     struct sockaddr_in clientService;
    14.  
    15.     char *sendbuf = "GET / HTTP/1.1\r\nHost:www.liveinternet.ru\r\nUser-Agent: Internet Explorer\r\n\r\n";
    16.     char recvbuf[DEFAULT_BUFLEN];
    17.     int recvbuflen = DEFAULT_BUFLEN;
    18.  
    19.     iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    20.     if (iResult != NO_ERROR) {
    21.       printf("WSAStartup failed: %d\n", iResult);
    22.       return 1;
    23.     }
    24.  
    25.     ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    26.     if (ConnectSocket == INVALID_SOCKET) {
    27.         printf("Error at socket(): %ld\n", WSAGetLastError() );
    28.         WSACleanup();
    29.         return 1;
    30.     }
    31.  
    32.     clientService.sin_family = AF_INET;
    33.     clientService.sin_addr.s_addr = inet_addr( "88.212.196.87" ); // айпи liveinternet.ru
    34.     clientService.sin_port = htons(80);
    35.  
    36.     iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
    37.     if ( iResult == SOCKET_ERROR) {
    38.         closesocket (ConnectSocket);
    39.         printf("Unable to connect to server: %ld\n", WSAGetLastError());
    40.         WSACleanup();
    41.         return 1;
    42.     }
    43.  
    44.     iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
    45.     if (iResult == SOCKET_ERROR) {
    46.         printf("send failed: %d\n", WSAGetLastError());
    47.         closesocket(ConnectSocket);
    48.         WSACleanup();
    49.         return 1;
    50.     }
    51.  
    52.     iResult = shutdown(ConnectSocket, SD_SEND);
    53.     if (iResult == SOCKET_ERROR) {
    54.         printf("shutdown failed: %d\n", WSAGetLastError());
    55.         closesocket(ConnectSocket);
    56.         WSACleanup();
    57.         return 1;
    58.     }
    59.  
    60.     do {
    61.  
    62.         iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
    63.         printf("%s",recvbuf);
    64.        
    65.     } while( iResult > 0 );
    66.  
    67.     closesocket(ConnectSocket);
    68.     WSACleanup();
    69.     return 0;
    70. }
    ASM вариант в аттаче (сорцы+exe)
     
  4. s0lidude

    s0lidude New Member

    Публикаций:
    0
    Регистрация:
    23 мар 2009
    Сообщения:
    14
    Адрес:
    ru
    ни у кого такого не возникало чтоль?
     
  5. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    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: после полного получения.
     
  6. iZzz32

    iZzz32 Sergey Sfeli

    Публикаций:
    0
    Регистрация:
    3 сен 2006
    Сообщения:
    355
    lstrcat добавляет в конец строки с завершающим нулём строку с завершающим нулём. С чего ты взял, что recv положит в buf1 именно такую строку? Добавляй ноль сам в [buf1+eax], предварительно проверив edi на -1, или получай данные прямо в нужное место msgText (mov esi, msgText; invoke recv ebx,esi,4096,0; (после проверки) add esi,eax).
     
  7. Flasher

    Flasher Member

    Публикаций:
    0
    Регистрация:
    31 янв 2004
    Сообщения:
    640
    Не лучще в подобных случиях юзать функции wininet ?
    Код (Text):
    1.                        @@:
    2.                            mov bytewrite,0
    3.                            invoke RtlZeroMemory,addr buffer,sizeof buffer
    4.                            invoke InternetReadFile,hRequest,addr buffer,sizeof buffer,addr bytewrite
    5.                             .if eax != 0 && bytewrite != 0
    6.                                jmp @B
    7.                             .endif
     
  8. iZzz32

    iZzz32 Sergey Sfeli

    Публикаций:
    0
    Регистрация:
    3 сен 2006
    Сообщения:
    355
    Оффтоп: Flasher, велосипеды изобретать обязательно (чтобы понять, как они работают), но не обязательно их использовать :)
     
  9. s0lidude

    s0lidude New Member

    Публикаций:
    0
    Регистрация:
    23 мар 2009
    Сообщения:
    14
    Адрес:
    ru
    q_q, это не имеет принципиального значения. я пробовал все это подставлять.

    iZzz32, причем тут lstrcat? попробуй удалить ее из цикла и просто оставить получение данных и проверку, все равно будет долго происходить.

    Кто-нить пробовал запускать это?

    Flasher, у меня нет проблем с получением данных, поэтому зачем мне альтернативы? У меня проблема в том, что получение просто затягивается, хотя если смотреть через откладчик, к примеру, то данные приходят мгновенно, а без отладчика - долго..
     
  10. iZzz32

    iZzz32 Sergey Sfeli

    Публикаций:
    0
    Регистрация:
    3 сен 2006
    Сообщения:
    355
    s0lidude, не запускал раньше, да. Замечание про буферы в силе. По твоему вопросу: Connection: close.
     
  11. s0lidude

    s0lidude New Member

    Публикаций:
    0
    Регистрация:
    23 мар 2009
    Сообщения:
    14
    Адрес:
    ru
    проблема решена.

    я неправильно цикл составлял.. если recv равен нулю, то нужно обрывать коннект.
     
  12. d4rkeagle

    d4rkeagle Алексей Шпунсель

    Публикаций:
    0
    Регистрация:
    3 мар 2006
    Сообщения:
    66
    Адрес:
    Тайланд
    s0lidude, тебе нужно было в асм коде заюзать функцию shutdown, прежде чем получать поток данных. т.к. shutdown закрывает открытый сокет, давая тем самым получить данные до конца. поэтому после того, как данных уже не будет, recv не будет ждать и сразу вернет управление.

    на крайняк, нужно задавать таймаут ожидания