Stackoverflow Java-Applet an C++-Server



  • Hallo!
    ich habe einen minimalen Server gebaut, der HTTP-Responses kann, mehr erst mal nicht. Ich habe ihn mit dem Client Firefox erfolgreich getestet. Sobald aber ein Java-Applet mir Daten senden will (die ich mit recv auffange), wird eine Exception geworfen: "Stack around the variable 'c' was corrupted."

    Der Visual Studio Debugger sagt, hier:

    bool tcp_server::recv_from(const int sock, std::string &s) {
        char c[500];
        int len = ::recv(sock, c, 499, 0);
        c[len] = '\0';
        s = c;
        return true;
    }
    

    Nun kann man maximal 499 Bytes empfangen, das letzte ist für die Nullterminierung. Bei der Zuweisung s = c (s ist ein std::string) wird die Exception von der CRT geworfen. Im C-Array sind 512 (!) Elemente zu sehen, allesamt ASCII-Müll.
    Das JavaApplet sendet eigentlich nur so:

    try
      {
       Socket skt = new Socket("90.136.135.38", 80);
       BufferedReader in = new BufferedReader(new
       InputStreamReader(skt.getInputStream()));
       System.out.print("Received string: '");
       while (!in.ready()) {}
       PrintWriter out = new PrintWriter(skt.getOutputStream(), true);
       out.print("Hallo Wie gehts denn so \0");
       System.out.println(in.readLine()); // Read one line and output it
       System.out.print("'\n");
       in.close();
      }
      catch(Exception e)
      {
       System.out.print("Whoops! It didn't work!\n");
      }
    

    Anmerkung: Nicht mein Code. 🙂

    Ist der Fehler im Java-Code zu finden? Clients, die mit C(++) gemacht sind, laufen einwandfrei, u.a. auch IE und Firefox, bei Java kackt's irgendwie ab. 😕



  • Sock0r schrieb:

    bool tcp_server::recv_from(const int sock, std::string &s) {
        char c[500];
        int len = ::recv(sock, c, 499, 0);
        c[len] = '\0';
        s = c;
        return true;
    }
    

    der code ist nicht von dir?

    nullterminierung brauchst du nicht

    const size_t RECV_LENGTH = 500;
    void tcp_server::recv_from(const int sock, std::string &s)
    {
        char c[RECV_LENGTH];
        int len = ::recv(sock, c, RECV_LENGTH, 0);
        if(len >= 0)
          s.append(c, c+len);
        else
          //disc oder so -> exception
    }
    

    ->

    const size_t RECV_LENGTH = 500;
    std::string tcp_server::recv_from(const int sock)
    {
        char c[RECV_LENGTH];
        int len = ::recv(sock, c, RECV_LENGTH, 0);
        if(len < 1)
          //disconnect oder so -> exception
        return std::string(c, c+len);
    }
    

    und wenn ich schon mal dabei bin, deinen Code zu kritisieren:
    std::vector wäre hier imho sehr viel logischer als std::string.
    Und seit wann schreibt man int statt SOCKET?

    const size_t RECV_LENGTH = 500;
    std::vector<char> tcp_server::recv_from(SOCKET sock)
    {
        char c[RECV_LENGTH];
        int len = ::recv(sock, c, RECV_LENGTH, 0);
        if(len < 1)
          //disconnect oder so -> exception
        return std::vector<char>(c, c+len);
    }
    

    kein Plan, ob da der Fehler lag - aber kann mir gut vorstellen, dass es bei nem disconnect gekracht hat, weil c[-1] nicht so gut ist^^

    bb



  • Das ist ein keep-alive-Socket. Getrennt wird da nix. Wo der Unterschied zwischen String und Vector<char> ist, ist mir so nicht klar. Und ehrlich gesagt sendet man Bytes, also chars, da ist ein std::string, der c_str() anbietet, wesentlich praktischer.
    SOCKET schreibe ich nicht. Wieso auch? Unter Win mag das üblich sein, in Linux eher nicht, dort nutzte ich eher int. Und es ist doch eh nurn typedef...

    Aber Ursache war's auch nicht. Ach, Java stinkt...



  • imho ist es nicht gerade naheliegende, z.bsp. binäre daten in nem string zu speichern...
    c_str() nützt dir genau so viel, wie &vector[0]
    die länge musst du trotzdem angeben, da binäre daten ja öfters mal ne 0 enthalten...
    und c_str() impliziert imho, dass die länge über strlen() festgestellt werden kann - bei &vector[0] ist klar, dass man noch ne länge braucht...

    btw: mal den debugger genutzt und geguckt, was genau passiert?

    bb



  • Gibt es denn einen Unterschied zwischen BYTE* und CHAR*? Der kann zwischen std::string und std::vector<char> ja auch nicht so groß sein, oder?

    Der Debugger macht das, was ich oben geschrieben habe. In Zeile "s = c" meldet er die oben genannte Fehlermeldung, die Inhalte des char-Arrays sind allesamt der gleiche ASCII-Schrott und der Index, den mir der Debugger anzeigt, geht bis 512.

    Das String-Terminierungszeichen muss ich aber angeben. Ein Test mit Firefox zeigt mir sonst in den nichtbelegten Bytes undefinierten ASCII-Müll. Wo soll das Zeichen auch herkommen? Mit ASCII-zeichen gehts, aber Java-Requests bringen Stack-Overflow. 😞



  • BYTE wird nen typedef auf nen unsigned char sein und iwo tief in der windows.h zu finden sein - vermut ich mal^^

    Nein - zwischen std::string und std::vector<char> sollte es (meistens) keinen Unterschied geben - abgesehen von nem Overhead von paar Byte bei string und die Millionen Funktionen, die string bietet die du nicht brauchst...

    "der Index, den mir der Debugger anzeigt, geht bis 512"
    das hat nichts zu sagen
    "allesamt der gleiche ASCII-Schrott"
    ist normal - im debug-mode initialisiert MSVC(ich nehm mal an, du nutzt den^^) alle variablen mit 0xc[...]c - hab gerad nachgeguckt, sollte -52 entsprechen...

    "Das String-Terminierungszeichen muss ich aber angeben."
    Es ist doch ne recv-Fkt - und keine Ausgabe-Fkt!?

    Naja - Fehler kann ich jedenfalls keine sehen - was anderes als "nutz den Debugger" kann ich dir auch nicht sagen : D

    bb


Anmelden zum Antworten