Sockets und das HTTP-Protokoll



  • gethostbyname sollte man nicht mehr benutzen, sondern man sollte getaddrinfo verwenden.

    Oh, das wusste ich gar nicht. Ich hatte mich nach Beej's Network Guide gerichtet. Ändern kann ich es leider nicht mehr aber ich habe eine Bemerkung am Ende ergänzt.

    Das ist IMHO falsch. Wenn die Verbindung venünftig beendet wird kriegt man das nur über recv mit.

    Tatsächlich. Vielen Dank, ich hab es jetzt im Artikel korrigiert.

    Zu WSAStartup: Wenn das fehlschlägt darf man WSAGetLastError nicht benutzen, sondern man muss den Rückgabewert als Fehlercode nehmen.

    Danke, ich hab's jetzt geändert und gebe den Rückgabewert aus.

    mfg.



  • Das eingescannte Bild ist einfach nur cool 🕶 👍



  • Das eingescannte Bild wirkt einfach nur billig.



  • Die Kompressionsrate des JPEGs ist nur zu hoch. Man kann deshalb fast nichts erkennen. Ansonst hat das Bild irgendwie einen gewissen Charme. 😃



  • Ja das Bid ist ein bisschen billig, das hab ich in einer langweiligen Geschichtsstunde gemalt 😃

    Falls jemand Zeit und Lust hat kann er ja versuchen es durch eine schöne Grafik zu ersetzen, ich kenn mich leider mit sowas nicht aus.

    mfg.



  • Ich hab den Text zwischen den Zeilen auf dem Bild verstanden.



  • scrub war so nett und hatt das Bild nachgebaut. Das neue Bild könnt ihr schon im Artikel bewundern, das alte Bild gibt's noch hier:
    http://www.c-plusplus.net/magazin/bilder/sockets_und_das_http-protokoll/hostent.jpg

    @scrub
    Vielen Dank für das Bild!! Ich hab noch eine Kleinigkeit geändert und die Auflösung etwas runter gesetzt damit auch 1024-User in den Genuss kommen.

    mfg.



  • joomoo schrieb:

    #ifdef linux
    #include <sys/socket.h> // socket(), connect()
    #include <arpa/inet.h> // sockaddr_in
    #else
    #include <winsock2.h>
    #endif
    

    Das ist ziemlich unportabel. Besser ist:

    /* all UNIX-like OSs (Linux, *BSD, MacOSX, Solaris, ...) */
    #if defined(unix) || defined(__unix) || defined(__unix__)
    #include <sys/socket.h>
    #include <arpa/inet.h>
    /* MS Windows */
    #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
    #include <winsock2.h>
    /* IBM OS/2 */
    #elif defined(OS2) || defined(_OS2) || defined(__OS2__) || defined(__TOS_OS2__)
    #include <sys/socket.h>
    #include <arpa/nameser.h>
    #else
    #error unsupported or unknown operating system.
    #endif
    


  • Fye schrieb:

    Besser ist...

    das ist ja schon mal ein anfang. kannst es ja noch ergänzen: http://predef.sourceforge.net/preos.html



  • Ich hab nicht gesagt, dass das vollständig ist. Ich mein halt, sich auf Windows und Linux zu beschränken und die armen BSD'ler und MacOSX'ler außen vor zu lassen ist nicht so toll. 😉

    BTW: Die Seite kenne ich. Was meinste, wo ich die Makros alle herhabe? 😉



  • Fye schrieb:

    Ich hab nicht gesagt, dass das vollständig ist. Ich mein halt, sich auf Windows und Linux zu beschränken und die armen BSD'ler und MacOSX'ler außen vor zu lassen ist nicht so toll. 😉

    aber os-halbe wird berücksichtigt. ein system dass seit 10 jahren kein schwein mehr verwendet 😉

    Fye schrieb:

    BTW: Die Seite kenne ich. Was meinste, wo ich die Makros alle herhabe? 😉

    selbst gebastelt? ich dachte das hast du aus irgendso'nem open source projekt rauskopiert...
    🙂



  • Müsste es nicht HTT-Protokoll und FT-Protokoll heißen?



  • void SendAll(int socket, const char* const buf, const size_t size)
    {
        size_t bytesSent = 0; // Anzahl Bytes die wir bereits vom Buffer gesendet haben
        do
        {
            bytesSent += send(socket, buf + bytesSent, size, 0);
            if(bytesSent < 0) // Wenn send einen Wert < 0 zurück gibt deutet dies auf einen Fehler hin.
            {
                throw CreateSocketError();
            }
        } while(bytesSent < size);
    }
    

    Ich habe den Artikel nur kurz überflogen, aber das sieht falsch aus - muss der dritte Parameter nicht size - bytesSent sein? Sonst liest send() unter Umständen über den Puffer hinaus. Außerdem kann es nach dem ersten Schleifendurchlauf passieren, dass bytesSent schon einen positiven Wert hat, send() etwas negatives zurückgibt und bytesSent danach aber immer noch positiv ist.



  • ck schrieb:

    void SendAll(int socket, const char* const buf, const size_t size)
    {
        size_t bytesSent = 0; // Anzahl Bytes die wir bereits vom Buffer gesendet haben
        do
        {
            bytesSent += send(socket, buf + bytesSent, size, 0);
            if(bytesSent < 0) // Wenn send einen Wert < 0 zurück gibt deutet dies auf einen Fehler hin.
            {
                throw CreateSocketError();
            }
        } while(bytesSent < size);
    }
    

    Ich habe den Artikel nur kurz überflogen, aber das sieht falsch aus - muss der dritte Parameter nicht size - bytesSent sein? Sonst liest send() unter Umständen über den Puffer hinaus. Außerdem kann es nach dem ersten Schleifendurchlauf passieren, dass bytesSent schon einen positiven Wert hat, send() etwas negatives zurückgibt und bytesSent danach aber immer noch positiv ist.

    glaube ich nicht, es muss wenn überahaut so heissen:

    bytesSent += send(socket, buf + bytesSent, size - bytesSent, 0);
    


  • Hallo ck und Parallan,

    Vielen Dank! Ihr habt natürlich Recht, ich wunder' mich warum ich so einen extremen Fehler machen konnte...
    Hier mal die überarbeite Version:

    void SendAll(int socket, const char* const buf, const size_t size)
    {
        size_t bytesSent = 0; // Anzahl Bytes die wir bereits vom Buffer gesendet haben
        do
        {
            size_t result = send(socket, buf + bytesSent, size - bytesSent, 0);
            if(result < 0) // Wenn send einen Wert < 0 zurück gibt deutet dies auf einen Fehler hin.
            {
                throw CreateSocketError();
            }
            bytesSent += result;
        } while(bytesSent < size);
    }
    

    Kann ich das so übernehmen?

    mfg.



  • Zumindest unter Linux gibt send nicht size_t sondern ssize_t zurück (und die MSDN sagt int, für Windows). size_t ist meines Wissens jedenfalls immer unsigned, deshalb ist die if(result < 0)-Abfrage nie falsch. Ich denke es reicht aus, für result einfach int zu nehmen. Sonst sieht es IMHO gut aus 🙂



  • ck schrieb:

    size_t ist meines Wissens jedenfalls immer unsigned, deshalb ist die if(result < 0)-Abfrage nie falsch.

    nie 'wahr' 😉
    aber hast recht, es muss ein signed-typ sein damit das funzt.
    übrigens: dieses 'throw' argument sollte besser 'SendError' oder so heissen 😉



  • Vielen Dank! Ihr habt Recht, ich weiß auch nicht wie ich auf size_t gekommen bin. Ich hab's jetzt schon im Artikel korrigiert, auf den FTP-Server komm ich gerade nicht drauf...

    Die CreateSocketError funktion hab ich so genannt, da sie ja noch nicht wirft sondern erstmal den SocketError erstellt.

    mfg.



  • #else
        int error = WSAGetLastError();
        char* msg;
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                      NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                      reinterpret_cast<char*>(&msg), 0, NULL);
        temp << "Socket-Fehler #" << error << ": " << msg;
    #endif
    

    Fehlt da nicht ein LocalFree? Und Leider kann auch FormatMessage fehl schlagen in welchem Fall das Program wahrscheinlich abstürzen würde. Dies passiert wenn kein Text gefunden wird was bei lokalisierten System leider hin und wieder passiert.



  • @joomoo

    Also weil's hier noch niemand getan hat: Vielen Dank für die tolle Anleitung. Solche Sachen geben immer einen Haufen Arbeit und das muss man auch mal loben 👍

    Gerade bei der Verarbeitung von 'chunked' Mode hilft mir dein Text jetzt weiter.

    Gruss, Peter


Anmelden zum Antworten