Sockets, warum ist mein code so langsam?



  • Zunächst das codebeispiel:

    #include <windows.h>
    #include <winsock.h>
    #include <stdio.h>
    #include <iostream>
    #include <conio.h>
    
    using namespace std;
    
    int main()
    {
      long socket_con;
      SOCKET socket_res;
      SOCKADDR_IN addr;
    
      #define BUF 4096
      char buffer[BUF];
    
     char *request;request = new char[4096];
    
      WSADATA wsa;
      socket_con = WSAStartup(MAKEWORD(2,0), &wsa);
    
     printf("Start time: %d \n",GetTickCount());
    
     for (int ids=500;ids<520;ids++)
     {
     socket_res = socket(AF_INET, SOCK_STREAM, 0);  
    
      memset(&addr, 0, sizeof(SOCKADDR_IN)); 
      addr.sin_family = AF_INET;
      addr.sin_port = htons(80); 
      addr.sin_addr.s_addr = inet_addr("IP ADDRESS");
     socket_con = connect(socket_res, (SOCKADDR*)&addr, sizeof(SOCKADDR));
    
     int ID=ids;
     sprintf(request,
    		"GET /website.php?ID=%d HTTP/1.1\r\n" 
    		"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.8.1.16) Gecko/20080702 Firefox/2.0.0.16\r\n"
    		"Host: hostname.com\r\n"
    		"Connection: Close\r\n" 
    		"Accept: */*\r\n"
    		"Accept-Encoding: text/html\r\n\r\n",ID);   
    
      send(socket_res, request, strlen(request), 0);
    
      char *filename = new char[256];
      sprintf(filename,"c:\\hostname\\%d",ID);
      FILE*f=fopen(filename,"wb");
      fclose(f);
    
      bool read=true;
      while(read)
        {
        socket_con = recv(socket_res, buffer, sizeof(buffer)-1, 0);
        if(socket_con <=0 )read=false;
        buffer[socket_con]='\0';
        FILE*f = fopen(filename,"ab");
    
        fputs(buffer,f);
        fclose(f);
        }
    
      printf("Part time: %d \n",GetTickCount());
    }
    closesocket(socket_res);
    WSACleanup();
    
      printf("End time: %d \n",GetTickCount());
      system("Pause");
      return 0;
    }
    

    Was ich hier machen möchte ist in einer schleife mehrere webseiten runterzuladen. Es funktioniert auch, jedoch total langsam. Nicht zu Vergleichen mit der Geschwindigkeit die ich für jede Seite einzeln benötigen würde.

    Wenn ich also nur eine Seite Lade ist die sogut wie sofort da. Aber schon eine 2te Seite dauert länger. Bis jetzt weiß ich nicht wieso,.. Es handelt sich dabei um Seiten von der Größe von ca. 25kb , also nicht wirklich viel Daten.

    Hat jemand ne Idee wie man was optimieren kann? Mein Ziel ist es mit FULLSPEED(dass was mein Internet und der Server hergibt) die seiten zu laden,..
    Es sind nämlich tausende und bei ca 3 Sekunden pro Seite( ist ca die Zeit die ich jetzt habe ) kann ich da Tage dran saugen.

    MfG Vincestooo



  • Ich hab' das jetzt nur kurz überflogen, aber vielleicht solltest du den socket auch da schließen, wo du ihn aufmachst (in der Schleife und nicht außerhalb).

    Ein paar error checks wären auch nicht schlecht.

    bool read=true;
      while(read)
        {
        socket_con = recv(socket_res, buffer, sizeof(buffer)-1, 0);
        if(socket_con <=0 )read=false;
    
        buffer[socket_con]='\0'; [b] --> schreibt bei socket error wohin?[/b]
    
        FILE*f = fopen(filename,"ab");
    
        fputs(buffer,f); [b] --> schreibt bei socket error was wohin?[/b]
        fclose(f);
        }
    

    wo ist das

    delete [] request;
    

    Fragen nach "Content-Length" oder "Transfer-Encoding: chunked" laß ich jetzt einfach mal weg.

    Wie gesagt - nur überflogen (1:43 Uhr).



  • Danke für die Tipps mit den Fehlern,.
    Das Schließen des Sockets hatte ich auch schon mal in der Schleife, hatte auch mal alles in der Schleife, und hat an Speed nix gebracht,.

    Vielleicht ists so langsam weil ich die requests nacheinander schicke?
    Könnten Threads die Sauggeschwindigkeit vielleicht erhöhen?

    Aber was ist nun:
    "Content-Length" oder "Transfer-Encoding: chunked" ???

    MfG Vincestooo



  • Vincestooo schrieb:

    Das Schließen des Sockets hatte ich auch schon mal in der Schleife, hatte auch mal alles in der Schleife, und hat an Speed nix gebracht,.

    Erst Korrektheit und dann Optimierungen (falls notwendig).
    Wenn ein Socket mit socket(..) erzeugt wird, muss es wieder mit closesocket(..) geschlossen werden.

    Das ist nicht der Fall, wenn das closesocket(..) ausserhalb der for- Schleife steht.

    Simon



  • Die Geschwindigkeit kann auch von der Gegenseite limitiert sein.

    Probier doch mal dieses Tools aus.
    http://www.gnu.org/software/wget/

    Simon



  • das hat zwar an sich nichts mit dem Geschwindigkeitsproblem, aber mir ist eine Sache aufgefallen.

    char *request;request = new char[4096];
    ...
    char *filename = new char[256];
    

    wenn du die feste Größe kennst, wieso new benutzen? Wieso nicht gleich

    char request[4096];
    ...
    char filename[256];
    

    außerdem gibst du den Speicher nicht frei.



  • Wenn der Server HTTP/1.1 kann, solltest du schauen, ob du nicht mehrere Anfragen über die gleiche Verbindung schicken kannst. Das dürfte eine Menge Zeit sparen.

    Ansonsten kannst du vielleicht zwei Prozesse laufen lassen. Parallel downloaden kann vielleicht etwas bringen.

    In der Schleife in der du die Daten einliest, solltest du nicht ständig die Datei öffnen und schließen. Unter Linux könntest du hier auch man: sendfile(2) nutzen, um vom Socket direkt in einen Datei zu schreiben. Vielleicht gibt es so etwas ähnliches für das OS deiner Wahl.

    Im übrigen solltest du dadrauf achten, dass der Code richtig eingerückt ist.



  • Hallo nochmal, danke für die Tipps,

    hab das ganze jetzt mit Threads gemacht und mich gewunderd wie schnell die Daten da waren. Also fast wie ein Fingerschnippen.
    Hier mal mein(noch nicht dynamischer) code, hoffe hab jetzt keine Fehler mehr drinne:

    #include <winsock.h>
    #include <stdio.h>
    #include <iostream>
    #include <conio.h>
    #include <windows.h>
    #include <cstdlib>
    using namespace std;
    DWORD WINAPI ThreadFunc(LPVOID data);
    
    int main()
    {
    int threadData=500;HANDLE thread = CreateThread(NULL, 0, ThreadFunc,&threadData,0,NULL);
    int threadData1=501;HANDLE thread1 = CreateThread(NULL, 0, ThreadFunc,&threadData1,0,NULL);
    int threadData2=502;HANDLE thread2 = CreateThread(NULL, 0, ThreadFunc,&threadData2,0,NULL);
    int threadData3=503;HANDLE thread3 = CreateThread(NULL, 0, ThreadFunc,&threadData3,0,NULL);
    int threadData4=504;HANDLE thread4 = CreateThread(NULL, 0, ThreadFunc,&threadData4,0,NULL);
    int threadData5=505;HANDLE thread5 = CreateThread(NULL, 0, ThreadFunc,&threadData5,0,NULL);
    int threadData6=506;HANDLE thread6 = CreateThread(NULL, 0, ThreadFunc,&threadData6,0,NULL);
    int threadData7=507;HANDLE thread7 = CreateThread(NULL, 0, ThreadFunc,&threadData7,0,NULL);
    int threadData8=508;HANDLE thread8 = CreateThread(NULL, 0, ThreadFunc,&threadData8,0,NULL);
    int threadData9=509;HANDLE thread9 = CreateThread(NULL, 0, ThreadFunc,&threadData9,0,NULL);
    int threadData10=510;HANDLE thread10 = CreateThread(NULL, 0, ThreadFunc,&threadData10,0,NULL);
    int threadData11=511;HANDLE thread11 = CreateThread(NULL, 0, ThreadFunc,&threadData11,0,NULL);
    int threadData12=512;HANDLE thread12 = CreateThread(NULL, 0, ThreadFunc,&threadData12,0,NULL);
    int threadData13=513;HANDLE thread13 = CreateThread(NULL, 0, ThreadFunc,&threadData13,0,NULL);
    int threadData14=514;HANDLE thread14 = CreateThread(NULL, 0, ThreadFunc,&threadData14,0,NULL);
    int threadData15=515;HANDLE thread15 = CreateThread(NULL, 0, ThreadFunc,&threadData15,0,NULL);
    int threadData16=516;HANDLE thread16 = CreateThread(NULL, 0, ThreadFunc,&threadData16,0,NULL);
    int threadData17=517;HANDLE thread17 = CreateThread(NULL, 0, ThreadFunc,&threadData17,0,NULL);
    int threadData18=518;HANDLE thread18 = CreateThread(NULL, 0, ThreadFunc,&threadData18,0,NULL);
    int threadData19=519;HANDLE thread19 = CreateThread(NULL, 0, ThreadFunc,&threadData19,0,NULL);
    system("PAUSE");
    return EXIT_SUCCESS;
    }
    
    DWORD WINAPI ThreadFunc(LPVOID data)
    {
          int *ID=(int*)data;
    
          long socket_con;
          SOCKET socket_res;
          SOCKADDR_IN addr;
    
          #define BUF 4096
          char buffer[BUF];
    
          char *request;
          request = new char[4096];
    
          WSADATA wsa;
          socket_con = WSAStartup(MAKEWORD(2,0), &wsa);
    
          socket_res = socket(AF_INET, SOCK_STREAM, 0);  
          memset(&addr, 0, sizeof(SOCKADDR_IN)); 
          addr.sin_family = AF_INET;
          addr.sin_port = htons(80); 
          addr.sin_addr.s_addr = inet_addr("IP INSIDE");
          socket_con = connect(socket_res, (SOCKADDR*)&addr, sizeof(SOCKADDR));
    
          sprintf(request,
    		"GET /website.php?ID=%d HTTP/1.1\r\n" 
    		"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.8.1.16) Gecko/20080702 Firefox/2.0.0.16\r\n"
    		"Host: hostname.com\r\n"
    		"Connection: Close\r\n" 
    		"Accept: */*\r\n"
    		"Accept-Encoding: text/html\r\n\r\n",*ID);   
    
          send(socket_res, request, strlen(request), 0);
          char *filename = new char[256];
          sprintf(filename,"c:\\hostname\\%d",*ID);
          FILE*f=fopen(filename,"wb");
          fclose(f);
          bool read=true;
          while(read)
          {
                     socket_con = recv(socket_res, buffer, sizeof(buffer)-1, 0);
                     if(socket_con <=0 )
                     {
                     read=false;
                     buffer[0]='\0';
                     }
                     else
                         buffer[socket_con]='\0';
          FILE*f = fopen(filename,"ab");
          fputs(buffer,f);
          fclose(f);
          }
          delete [] filename;
          closesocket(socket_res);
          WSACleanup();
          delete [] request;
          return 0;
    }
    

    MfG Vincestooo



  • Vincestooo schrieb:

    Aber was ist nun:
    "Content-Length" oder "Transfer-Encoding: chunked" ???

    MfG Vincestooo

    "Transfer-Encoding: chunked"
    http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6

    "Content-Length"
    http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13

    Lies
    http://www.w3.org/Protocols/rfc2616/rfc2616.html
    (mehrmals und gründlich) wenn du das HTTP-Protokoll benutzen willst.

    Abgesehen davon, daß es für das OS ziemlich viel Aufwand bedeutet einen Socket zu kreieren und es außerdem nicht sehr "freundlich" ist 20 threads gleichzeitig auf einen server loszulassen, könntest du mit HTTP 1.1

    statt "Connection: Close\r\n" "Connection: Keep-Alive\r\n" benutzen und

    socket_res = socket(AF_INET, SOCK_STREAM, 0);
    
    memset(&addr, 0, sizeof(SOCKADDR_IN));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(80);
    addr.sin_addr.s_addr = inet_addr("IP ADDRESS");
    socket_con = connect(socket_res, (SOCKADDR*)&addr, sizeof(SOCKADDR));
    

    aus deinem ersten code einfach vor die Schleife setzen (closesocket() dann natürlich da lassen wo es war).

    Zu deinem threaded code möchte ich im Moment eher nix sagen, außer wie schon von rüdiger gesagt:
    file vor der Schleife 1 mal öffnen und danach 1 x schließen.

    Edit: 2-3 Sachen noch:
    Warum wohl hat irgendein schlauer Mensch mal Schleifen erfunden?

    Was passiert wenn socket() oder connect() fehlschlägt?
    Was passiert wenn send() nicht auf eimal deinen request sendet sondern nur einen Teil?


Anmelden zum Antworten