Netzwerkprogrammierung auf C oder C++?



  • santa1982 schrieb:

    Wurst... richtig?

    Wenn das Ziel ist Netzwerkprogrammierung zu lernen: Ja. Mach es dir nicht unnötig schwer. Wenn du das dann verstanden hast und ein Programm machen möchtest, dass das Netzwerk nur als notwendiges Übel missbraucht, kannst du immer noch gucken, ob du dir eigene Socket Klasse baust oder irgendeine Bibliothek dafür verwendest.



  • Das ist leider richtig. Aber zumindest eine grundlegende Einführung gibts hier: http://www.highscore.de/cpp/boost/asio.html#asio_netzwerkprogrammierung



  • 314159265358979 schrieb:

    P.S.: Ich seh schon cooky, wie er mich am liebsten erschlagen würde. Nur weil du asio nicht kennst!

    Hoere einfach auf, Leuten Worte in den Mund zu legen.



  • dudewhat



  • Pi macht sich mal wieder lächerlich 🙄



  • Back to topic. Alle. Kein "der hat angefangen", kein geflame mehr. Sind doch nicht im Kindergarten hier.



  • Asio ist das Allerletzte für Anfänger. Asio ist overengineered und viel zu mächtig.
    Einfach n bischen die BSD/POSIX/Windows Sockets wrappen (das schreit doch nach ner Klasse 'Socket') und los gehts. 😉



  • > (das schreit doch nach ner Klasse 'Socket')

    Das schreit nach Bufferoverlows und noch mehr Netzwerk-Exploits, weil immer wieder von vorne das selbe programmiert wird und dabei (besonders bei recv()) dramatische Fehler gemacht werden. asio ist nicht overengineerd und schon garnicht zu mächtig. Hast du z.B. schon mal auf echter API mit Dual Stack Sockets gearbeitet? Weißt du wie viel Aufwand das ist? Weißt du, dass heutzutage Anwendungen ohne IPv6-Kompatibilität dumm sind? Ein _gutes_ Netzwerkprogramm in reiner API ist so schwer zu schreiben und zu debuggen, dass man besser Bibliotheken nutzt.
    An asio stoßen sich viele Anfänger die Köpfe, weil Codeteile eben parallel (sprich asynchron) ablaufen, Threadsicherheit eine Rolle spielen kann etc. Aber es gibt noch sehr viele andere gute (und evtl. leichtere, wenn auch weniger performant und allgemeinnützlich), z.B. Poco.Net



  • Jodocus schrieb:

    > (das schreit doch nach ner Klasse 'Socket')

    Das schreit nach Bufferoverlows und noch mehr Netzwerk-Exploits, weil immer wieder von vorne das selbe programmiert wird und dabei (besonders bei recv()) dramatische Fehler gemacht werden.

    Vollkommen richtig, zum Lernen kann es aber trotzdem sinnvoll sein, hängt imho vom Typ Mensch ab 🙂



  • Er möchte lernen und nicht zwingend gleich eine voll ausgestattete Anwendung schreiben. Und wie das Ganze funktioniert lernt man doch deutlich besser mit den Low-Level Sockets, er kann ja immer noch auf Asio wechseln.

    Und so schwer ist es wirklich nicht, das ganze sicher zu machen.



  • Jodocus schrieb:

    Das schreit nach Bufferoverlows und noch mehr Netzwerk-Exploits,

    Genau, denn er wird bestimmt gleich ein relevantes Netzwerkprogramm schreiben, für das dann Exploits entwickelt werden.

    Jodocus schrieb:

    weil immer wieder von vorne das selbe programmiert wird und dabei (besonders bei recv()) dramatische Fehler gemacht werden.

    Jau, bei recv() kann man super viel falsch machen. 😃



  • Dann werde ich mich mit Heldenmut dafür einsetzen dass durch recv keine Bufferoverflows mehr geschehen.

    std::vector<char> read_socket(int sock, std::size_t amount)
    {
       std::vector<char> buffer(amount);
    
       std::size_t read_total = 0;
       while(read_total != amount)
       {
          int this_read = recv(sock, &buffer[0] + read_total,
             buffer.size() - read_total, MSG_WAITALL);
          if(this_read == -1)
             throw std::runtime_error("socket recv error");
          if(this_read == 0)
          {
             buffer.resize(read_total);
             break;
          }
    
          read_total += this_read;
       }
    
       return buffer;
    }
    

    Verflixt war das schwer.



  • > Er möchte lernen und nicht zwingend gleich eine voll ausgestattete Anwendung schreiben.

    Aber er möchte das lernen, um sowas zu machen. Was denkst du, wo die Exploits in den "großen Anwendungen" herkommen? Genau, weil Leute dachten, sie hätten es in ihren Spielchen verstanden und dann Software "fürs echte Leben" geschrieben haben.

    > Und wie das Ganze funktioniert lernt man doch deutlich besser mit den Low-Level Sockets, er kann ja immer noch auf Asio wechseln.

    Ist genau die selbe Logik in der "Zuerst C-Strings oder C++-Strings"-Debatte. Und ich bleibe dabei. Besser erst C++-Strings, besser erst eine Socket-Abstraktionsebene höher. Sich vertiefen kann man immernoch, wenn man es braucht. Dann kann man auch eine eigene Abstraktion schreiben und die Low-Level-Sachen durchprogrammieren, um zu sehen, wie sie funktioniert aber dann wieder die fertige und gut getestete Library nehmen (wie bei std::string). Und Socket-Librarys verschleiern GANZ sicher nicht die Socket-Semantik. Sie vereinfachen lediglich die API. Wenn 5 von 8 Funktionsparametern für einen Anfänger nicht relevant sind (z.B. QoS, diverse Flags etc.), dann hilft ihm das nicht, Sockets zu verstehen. Es geht schließlich ums wesentliche, und gute Library-Interfaces nötigen einen nichts unwesentliches auf, behalten dem Programmierer aber auch keine Details vor, wenn sie sie benötigen.

    > Genau, denn er wird bestimmt gleich ein relevantes Netzwerkprogramm schreiben, für das dann Exploits entwickelt werden.

    Gleiches wie oben. Manche dachten, sie hätten recv() und deren Rückgabewert verstanden und programmierten damit dann "echte" Software.

    > Jau, bei recv() kann man super viel falsch machen. 😃

    Ich hoffe dass das keine Ironie war.



  • Ethon schrieb:

    Dann werde ich mich mit Heldenmut dafür einsetzen dass durch recv keine Bufferoverflows mehr geschehen.

    std::vector<char> read_socket(int sock, std::size_t amount)
    {
       std::vector<char> buffer(amount);
       
       std::size_t read_total = 0;
       while(read_total != amount)
       {
          int this_read = recv(sock, &buffer[0] + read_total,
             buffer.size() - read_total, MSG_WAITALL);
          if(this_read == -1)
             throw std::runtime_error("socket recv error");
          if(this_read == 0)
          {
             buffer.resize(read_total);
             break;
          }
          
          read_total += this_read;
       }
       
       return buffer;
    }
    

    Verflixt war das schwer.

    Toll. Dann können Anfänger ja gleich eine Library nutzen, wenn sie statt recv() read_socket() nehmen sollten. Und da haben sie auch mehr Kontrolle über Flags, denn deine Funktion hier ist schon eine Einschränkung des Interface.
    Und es geht außerdem nicht nur um recv(). Andere Gefahrenquellen wären etwa conditional Accept (SYN-Flood) und exklusive Adressen, die Servern ihren Port klauen.



  • Jodocus schrieb:

    Ich hoffe dass das keine Ironie war.

    Natürlich war das Ironie. Aber ich bin gespannt auf ein Beispiel, das die komplexen Fehler die bei recv() gemacht werden können veranschaulicht.



  • Schau dir mal Ethons Code an und schau dir an, was man da alles falsch machen kann. Google "recv() buffer overflow" sollte genug anschauliche Resultate liefern.



  • recv liefert nicht unbedingt die Anzahl an Bytes zurück, die man angegeben hat. Vorallem auch nicht in der Aufteilung, wie sie versendet wurden. Das ist tatsächlich ein großes Fehlerpotential. Weiß aber nicht, ob er das meint.



  • Jodocus schrieb:

    Schau dir mal Ethons Code an und schau dir an, was man da alles falsch machen kann. Google "recv() buffer overflow" sollte genug anschauliche Resultate liefern.

    Ernsthaft, bei den Beispielen die ich da finde, kannst du auch sagen memcpy oder strlen wären super gefährlich. Also entweder ich sehe den Fehler gerade nicht, oder man sollte einfach mal davon ausgehen, dass man ein Volldepp sein muss um recv() falsch zu nutzen.
    Ich habe jedenfalls noch kein Beispiel gesehen, bei dem der Fehler nicht sofort in's Auge springen würde.



  • asio vorzuschlagen is echt das dümmste was man nur machen kann. Zum Lernen einfach ein winsocket Tutorial durcharbeiten und dann ne kleine Klasse basteln.



  • Grund?


Anmelden zum Antworten