socket blockt beim 2. loop



  • Hi Leute,
    könnt ihr mir vielleicht weiterhelfen, möchte den Content einer Website über Debian runterladen, was fällt einem da ein? - sockets genau!
    So habe da mal ein kleines progrämmchen geschrieben welches dies per GET Request durchführt.
    Leider ist es nur so das der 2. recv total blockiert (blocking socket).
    Ich weiss aber das noch was kommt!
    Ich bekomme so wie definiert erstmal nur 1023 Bytes pro call.
    Das ganze kann mit g++ problemlos kompiliert werden und muss beim starten nichtmehr parameterisiert werden.
    Wäre cool wenn mir jem. helfen könnte, komme leider aus der windowswelt und
    hab kein mögl. das ganze zu debuggen.
    Thx!

    /* INCLUDES */
    #include <string.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <stdio.h>
    #include <arpa/inet.h>
    #include <time.h>
    #include <netdb.h> 
    
    #define DEST_IP "66.249.85.104"
    #define DEST_PORT 80
    #define GET_REQUEST "GET http://www.google.de HTTP/1.1 \nHost: www.google.de \nConnection: Keep-Alive\r\n\r\n"
    #define MAX_BUF_SIZE 1024
    #define MAX_TIMEOUT 5;
    
    /* MAIN FUNCTION PROG START */
    int main()
    {
      int i_sock;                                                                   // our socket handle
      struct sockaddr_in sock_dest;                                                 // our destination structur
    
      //Setting Socket attributes
      sock_dest.sin_family=AF_INET;                                                 // socket family
      sock_dest.sin_port=htons(DEST_PORT);                                          // socket destinaton port
      inet_aton(DEST_IP,&(sock_dest.sin_addr));                                     // socket destination address
      memset(&(sock_dest.sin_zero),'\0',8);                                         // zero the rest of the structure
    
      i_sock = socket(AF_INET, SOCK_STREAM, 0);                                     // try to create a new socket()
      if (i_sock != -1)
      {
        if (connect(i_sock,(struct sockaddr *)&sock_dest,sizeof(sock_dest))!=-1)
        {
          char *pdata=new char[255];
          int nlen,nsend,nrecv;
    
          // HTTP REQUEST
          sprintf(pdata,GET_REQUEST);
    
          nlen=strlen(pdata);
          printf("%s\r\n",pdata);
          nsend=send(i_sock,pdata,nlen,0);                                          // Sending data
          printf("(%i) Byte(s) sent!\r\n",nsend);
          delete [] pdata;  
    
          char *precv=new char[MAX_BUF_SIZE];
          while (1)                                                                 //Trying to receive data
          {
            while ((nrecv= recv(i_sock,precv,(MAX_BUF_SIZE-1),0))>0)
            {
              printf("%s",precv);
            }
            break;
          }           
          delete [] precv;              
          printf("Closing socket()!\r\n");
          //close(i_sock);
        }
        else
        {
          printf("%s","error_02: Can´t connect to host!\r\n");
        }
      }
      else
      {
        printf("%s","error_01: Can´t create Socket()!\r\n");
      }
      return 0;
    }
    


  • #define GET_REQUEST "GET / HTTP/1.1\r\nHost: www.google.de\r\nConnection: close\r\n\r\n"
    


  • genial @ ...
    Vielen Dank!!
    Sagmal kannst du mir vielleicht sagen in welchem header ich die Definition für:
    `close' undeclared (first use this function)
    Socket close finde.
    Beim Sniffern vom IE7 wird keepalive verwendet, der arbeitet wohl mit asyncsockets.





  • Beim Sniffern vom IE7 wird keepalive verwendet, der arbeitet wohl mit asyncsockets.

    Das ist dafür da das man mehrere Abfragen hintereinander stellen kann ohne jedes mal eine neue Verbindung aufbauen zu müssen.



  • Hier ein paar Verbesserungsvorschläge:

    Shib schrieb:

    char *pdata=new char[255];
    ...
          delete [] pdata;
    

    Das ist unnötig. Du solltest besser Deinen Puffer auf den Stack legen:

    char pdata[255];
    ...
          // kein Aufräumen notwendig
    

    Damit vermeidest Du Memoryleaks. Man sollte dynamischen Speicher vermeiden wo immer es geht. Soll die Puffergröße variabel sein, dann geht auch ein std::vector:

    std::vector<char> vdata(bufsize);
          char* pdata = &vdata[0];
    ...
          // wieder kein Aufräumen notwendig
    

    Shib schrieb:

    while ((nrecv= recv(i_sock,precv,(MAX_BUF_SIZE-1),0))>0)
    

    Hier kannst Du ruhig MAX_BUF_SIZE Bytes lesen. Warum willst Du das letzte Byte Deines Puffers nicht nutzen?

    Im übrigen solltest Du alle Request-Header mit "\r\n" abschliessen. Nur mit "\n" geht zwar auch, ist aber nicht standardkonform.

    Statt zu sniffen empfehle ich Dir den entsprechenden Standard rfc 2616 anzuschauen (http://www.ietf.org/rfc/rfc2616.txt). Ist gar nicht so schwer, wenn man sich mal rein gelesen hat. Dort stehen dann auch solche Sachen wie der Connection-Header.

    Wie schon erwähnt bedeutet der, daß die Verbindung nicht abgebaut wird. Der Server antwortet in der Regel mit einem Header "Connection: Keep-Alive" und muß dan ein Header "Content-Size: nnn" liefern, damit der Client weiß, wie viele Bytes er nach den Headern noch zu lesen hat.

    Noch einfacher kannst Du Dir das machen, wenn Du entsprechende Bibliotheken verwendest, wie z. B. meine cxxtools (http://www.tntnet.org/cxxtools.hms, demnächst auch im Debian-repository). Da schreibst Du einfach:

    #include <cxxtools/httprequest.h>
    #include <cxxtools/httpreply.h>
    
    int main(int argc, char* argv[])
    {
      try
      {
        cxxtools::HttpRequest request("http://www.google.de");
        cxxtools::HttpReply reply(request);
        // HttpReqply ist ein std::istream, wo Du die Daten lesen kannst:
        // (zur Erinnerung: operator<<(std::ostream&, std::streambuf*) kopiert
        // alles was geht)
        std::cout << reply.rdbuf() << std::flush;
        return 0;
      }
      catch (const std::exception& e)
      {
        std::cerr << e.what() << std::endl;
        return 1;
      }
    }
    

    Tntnet



  • danke erstmal @ unregistered leute.
    Cool tntnet, fand bisher bei C die dynamische Memoryallocation aufm heap ziemlich cool und dachte das die relativ performant ist (malloc) usw.
    Das mit den vectorteilen interessiert mich extrem, hab die Syntax noch nicht so ganz verstanden und vorallem was ist wenn eine funktion einen char* erwartet kann ich dann einen vector übergeben?
    Danke tntnet!
    BTW. RFC hab ich schon gelesen alles GET nur auf die KeepAlive hab ich nich geachtet!
    Thx!



  • ok ist klar ich setzt einfach einen (char) Zeiger auf das jeweilige byte (0).
    Kann ich diese vectordinger nachträglich resizen, wenn ich z.B. so ne art Ringspeicher verwenden will.
    z.B. in der Loop.
    ->hole daten in tempspeicher
    ->vergrössere vector und hänge tempspeicher dran
    Danke



  • Der vector läßt sich auch nachträglich in der Größe verändern. Du mußt allerdings aufpassen, daß alle Zeiger in die Daten dadurch in der Regel ungültig werden. Das geht beispielsweise:

    std::vector buffer(256);
    char* ptr = &buffer[0]; // ptr zeigt jetzt auf 256 Bytes verfügbaren Speicher
    // hier kannst Du die 256 Bytes füllen
    buffer.resize(512);     // ptr ist ab hier ungültig
    ptr = &buffer[256];     // jetzt zeigt ptr auf die nächsten 256 Bytes
    

    Intern wird natürlich malloc verwendet. Performancemässig macht das keinen Unterschied. Der wesentilche Unterschied ist halt, daß Du den Speicher nicht frei geben musst. Und Exceptionsafe ist der Code dann auch.


Anmelden zum Antworten