Sourcecodes von Websites teilw. fehlerhaft geladen



  • Die Sockets greifen auf winsock.h zurück.
    libwsock32.a entsprechend.
    Oder meintest du was anderes?



  • falsches forum. winapi ist nebenan.
    wo tauchen die fehler auf, nur am ende? dann fehlt vielleicht die 0 am ende.
    ansonsten ist das zu wenig code um mehr zu sagen.



  • post doch nochmal im winapi forum, und post ein bißchen(!) mehr infos.
    (was ist str? wie ist recv implementiert?)

    ich weiß nicht ob es daran liegt aber die soweit ich weiß mußt du an die char* die du von der recv funktion kriegst noch ein '\0' hängen. bin mir aber nicht mehr sicher



  • Nein, mitten im String stehen manchmal sinnlose Zeichen, manchmal aber auch nicht. Bei ein und derselben Seite scheinbar zufällig.
    Kann das sein, dass er evtl. mit Sonderzeichen nicht klar kommt?
    Ich also auf eine andere Codierung zurückgreifen muss?

    Was fehlt dir noch an Code?
    Brauchst du die Klasse sock?
    Ansonsten passiert da nichts spannendes mehr. Der Fehler tritt schon auf, wenn ich str auf der Standardausgabe ausgebe. Oder äußert sich halt so, dass str.find(...) eigentlich vorhandene Strings nicht findet, weil sie durch Sonderzeichen unterbrochen sind.



  • wie gesagt winapi forum



  • Dann bitte verschieben, wenn ein Mod das sieht.

    str ist ein normaler String.
    Code für Socket stammt größtenteils aus einem Buch und sieht so aus:

    // socket.h
    #ifndef _SOCKET_H_
    #define _SOCKET_H_
    
    #include <winsock.h>
    #include <string>
    #include <windows.h>
    #include <io.h>
    
    const int MAXRECV = 1024;
    
    class Socket
    {
        private:
        int m_sock;
        sockaddr_in m_addr;
    
        public:
        Socket();
        virtual ~Socket();
    
        bool create();
        bool bind(const int port);
        //bool listen();
        //bool accept();
        bool connect(const std::string host, const int port);
    
        bool send(const std::string) const;
        int recv(std::string&) const;
    
        bool close() const;
    
        void cleanup() const;
        bool is_valid() const {return m_sock != -1;}
    };
    
    #endif
    
    //socket.cpp
    
    #include "socket.h"
    
    #include <cstdlib>
    #include <iostream>
    #include <io.h>
    #include <windows.h>
    #include <winsock2.h>
    
    using namespace std;
    
    Socket::Socket() : m_sock(0)
    {
        //Windows DLL intitialisieren
        WORD wVersionRequested;
        WSADATA wsaData;
        wVersionRequested = MAKEWORD (2,2);
        if(WSAStartup (wVersionRequested, &wsaData) != 0)
        {
            cout << "Fehler beim Initialisieren von Winsock\n";
            exit(1);
        }
    }
    
    Socket::~Socket()
    {
        if( is_valid() )
        ::closesocket(m_sock);
    }
    
    bool Socket::create()
    {
        m_sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if(m_sock < 0)
        {
            cout << "Fehler beim Anlegen eines Sockets\n";
            exit(1);
        }
        return true;
    }
    
    //Erzeugt Bindung an Serveradresse/ Port
    bool Socket::bind( const int port )
    {
        if ( ! is_valid() )             // Socket nicht korrekt
        {
            return false;
        }
        m_addr.sin_family = AF_INET;
        m_addr.sin_addr.s_addr = INADDR_ANY;
        m_addr.sin_port = htons(port);          // in Network-Byte-Order umwandeln
    
                        // Scope-Operator => Aufruf der API-Fkt. bind()
        int bind_return = ::bind(m_sock, (struct sockaddr* )&m_addr, sizeof(m_addr));
                                        // Umwandlung in von bind() erfordete Struktur
        if(bind_return==-1) return false;
    
        return true;
    }
    
    bool Socket::connect(const string host, const int port)
    {
        if( !is_valid() ) return false;
    
        struct hostent* host_info;
        unsigned long addr;
        //mit Nullen füllen
        memset( &m_addr, 0, sizeof(m_addr));
    
        if( addr = inet_addr( host.c_str() ) != INADDR_NONE )
            // wenn host gültige numerische Adresse enthält
        {
            memcpy( (char*)&m_addr.sin_addr, &addr, sizeof(addr));      //Adresstruktur füllen
        }
        else   // keine gültige numerische Adresse
        {
            host_info = gethostbyname(host.c_str());
            if(NULL == host_info)
            {
                cout << "Unbekannter Server\n";
                exit(1);
            }
            memcpy( (char*)&m_addr.sin_addr, host_info->h_addr, host_info->h_length);
        }
        // Rest der Adressstruktur füllen
        m_addr.sin_family = AF_INET;
        m_addr.sin_port = htons(port);
    
        int status = ::connect(m_sock, (sockaddr*)&m_addr, sizeof(m_addr));
                    // API-Fkt.
        if(status==0) return true;
        else          return false;
    }
    
    bool Socket::send( const string s ) const
    {
        int status = ::send (m_sock, s.c_str(), s.size(), 0);
        if(status==-1)
        {
            return false;
        }
        else
        {
            return true;
        }
    }
    
    int Socket::recv(string& s) const
    {
        cout << "Socket::recv startet\n";
        char buf[MAXRECV +1];
        s="";
        int status = -1;
    
        while(status!=0)
        {
        // buffer mit Nullen füllen
        memset(buf, 0, MAXRECV);
    
        status = ::recv(m_sock, buf, MAXRECV, 0);
        if(status>0 || status != SOCKET_ERROR)
        {
            s.append(buf);
        }
        else
        {
            cout << "Fehler in Socket::recv\n";
            cout << WSAGetLastError();
    
            exit(1);
            return 0;
        }
        }
        cout << "Verbindung beendet\n";
        return status;
    }
    
    bool Socket::close() const
    {
        closesocket(m_sock);
        cleanup();
        return true;
    }
    
    void Socket::cleanup() const
    {
        WSACleanup();
    }
    


  • Sinthoras schrieb:

    Nein, mitten im String stehen manchmal sinnlose Zeichen, manchmal aber auch nicht.

    Ich würde mal sagen: Manche Seiten sind mit UTF-8 codiert und manche mit ISO-8859-1
    Das wird vrmtl im Header der Seite irgendwo stehen - und du wirst nicht drum rum kommen den string in einen wstring zu konvertieren...
    Bin mir zwar jz nicht zu 100% sicher aber das findest du leicht heraus in dem du nen paar Tests machst...

    Fencer schrieb:

    soweit ich weiß mußt du an die char* die du von der recv funktion kriegst noch ein '\0' hängen.

    Für den Fall, dass man das ausgeben will, wird das zu 99% stimmen ^^ Aber eigtl sollte das seine Funktion schon machen: (und er arbeitet ja eh mit std::string - also ist das nicht der Fehler - die Funktion an sich aber schon ^^)

    int Socket::recv(string& s) const
    {
        char buf[MAXRECV +1]; //nimm die +1 weg
        s="";
        int status = -1;
    
    //  while(status!=0)  //prüfst du doch in der Schleife schon...
        for ( ;; )
        {
    //      memset(buf, 0, MAXRECV); //1. unnötig und 2. warum nicht auch das letzte zeichen?
    
            status = ::recv(m_sock, buf, MAXRECV, 0);
    //      if(status>0 || status != SOCKET_ERROR)
            if(status == 0)
               break; //die Verbindung wurde erfolgreich beendet - du hast also entweder alle Daten ODER aber zumindest einen Teil
            if(status == SOCKET_ERROR)
               return SOCKET_ERROR;
    
    //      s.append(buf); //so einfach geht das nicht (die Länge wird nicht um sonst wiedergegeben - weil eben auch in der Mitte eine '\0' stehen kann - je nachdem, welche Inhalte da drin sind und wie die Kodierung ist
            const std::string tmp(buf, buf+status);
            s.append(tmp);
        }
    //  return status; //falsch!
        return s.length();
    }
    

    Sie ist noch immer nicht perfekt aber wenigsten sollte sie jz auch das machen, was sie sollte ^^

    bb



  • status = ::recv(m_sock, buf, MAXRECV, 0); 
        if(status>0 || status != SOCKET_ERROR) 
        { 
            s.append(buf); 
        }
    

    recv tut nicht 0 terminieren tun



  • Shade Of Mine schrieb:

    status = ::recv(m_sock, buf, MAXRECV, 0); 
        if(status>0 || status != SOCKET_ERROR) 
        { 
            s.append(buf); 
        }
    

    recv tut nicht 0 terminieren tun

    dafür hat er ja obendrüber das mit dem memset gemacht gehabt... das war also nicht der fehler (abgesehen davon, was passiert wenn recv auch [c]maxrecv[c] zeichen empfängt - aber ok ^^

    bb



  • unskilled schrieb:

    was passiert wenn recv auch [c]maxrecv[c] zeichen empfängt

    genau.



  • Vielen, vielen Dank für dich vielen Antworten und die große Mühe!

    @unskilled:
    Speziell für Deine Mühe vielen Dank.
    Die recv-Funktion hab ich aus dem Buch abgeschrieben. Hat auch bisher getan, was sie sollte.
    Deine tut es auch, ich nehm dann wohl die, wenn es so richtig ist...
    Danke.

    Was ich immernoch nicht verstanden habe: Wieso bekomme ich bei ein und derselben Seite mal den richtigen Quellcode und mal noch ein paar fehlerhafte Zeichen dazu?
    Kommt er nur manchmal mit der Formatierung klar?!? Das kommt mir wirklich seltsam vor. Wenn es wenigstens immer oder nie falsch wäre...

    Edit:
    Der Quelltext ist formatiert nach iso-8859-1.
    Kann ich da bei string bleiben?
    (Ich hab leider null Ahnung von Stringkodierungen...)



  • Sinthoras schrieb:

    Edit:
    Der Quelltext ist formatiert nach iso-8859-1.
    Kann ich da bei string bleiben?
    (Ich hab leider null Ahnung von Stringkodierungen...)

    Ich leider auch nicht ^^
    musste mal wikipedia gucken ^^
    ansonsten weiß ich leider nicht, warum es mal falsch und mal richtig ist... dann konnte es auch eher weniger an der fkt liegen... ><

    bb



  • Sinthoras schrieb:

    // socket.h
    #ifndef _SOCKET_H_
    #define _SOCKET_H_
    
    #include <winsock.h>
    #include <string>
    #include <windows.h>
    #include <io.h>
    
    const int MAXRECV = 1024;
    
    class Socket
    {
        private:
        int m_sock;
        sockaddr_in m_addr;
    
        public:
        Socket();
        virtual ~Socket();
    
        bool create();
        bool bind(const int port);
        //bool listen();
        //bool accept();
        bool connect(const std::string host, const int port);
    
        bool send(const std::string) const; // ???
        int recv(std::string&) const; // ???
    
        bool close() const; // ???
    
        void cleanup() const; // ???
        bool is_valid() const {return m_sock != -1;}
    };
    
    #endif
    

    Überdenk mal deinen eigensinnigen Umgang mit const 😉
    Nicht alles was sich als const compilieren lässt sollte man auch const machen. Dinge wie send/recv bzw. read/write würde ich auf keinen Fall const machen -- schliesslich haben diese Funktionen ja durchaus nicht zu vernachlässigende Seiteneffekte.

    Einzig ein "read" in einer File-Klasse die keinen "File-Pointer" verwaltet (bzw. eine "Variante" von Read die diesen File-Pointer nicht ändert) würde ich als const ansehen, da sich dadurch der Zustand des Objektes ja wirklich nicht ändert.

    Anders gesagt: const sollten IMO nur Dinge sein, bei denen es keine Rolle spielt ob man sie wiederholt, oder ganz weglässt (ganz weglassen geht natürlich nur sofern man das Ergebnis nicht auswertet). Und bei send/recv/close/... auf einen Socket ist das ja ganz sicher nicht gegeben.



  • Ich hab gelesen, ich solle das alles const machen. Aber ich muss gestehen, ich weiß nicht, warum...
    Könntest du mir erklären, was hier das Problem ist bzw. was sich dadurch ändert?
    Ich dachte, ich sage dem Compiler damit nur, dass meine Methode das Objekt nicht ändert. Nicht?

    Davon ab: Weiß vielleicht doch jemand, warum der Quelltext mal richtig, mal falsch geladen wird?

    LG



  • Sinthoras schrieb:

    Davon ab: Weiß vielleicht doch jemand, warum der Quelltext mal richtig, mal falsch geladen wird?

    steht doch schon da oben: du liest MAXRECV bytes ein und hast dann keine abschließende 0 mehr. beim anhängen an den string hängts dann vom zufall ab, wo der string terminiert wird (nämlich bei der ersten zufällig gefundenen 0 im speicher hinter dem string).

    versuch doch mal mit

    status = ::recv(m_sock, buf, MAXRECV - 1, 0);
    

    dann wird die 0 auch nicht überschrieben.



  • Sinthoras schrieb:

    @unskilled:
    [...]
    Die recv-Funktion hab ich aus dem Buch abgeschrieben. Hat auch bisher getan, was sie sollte.
    Deine tut es auch, ich nehm dann wohl die, wenn es so richtig ist...
    Danke.

    Was ich immernoch nicht verstanden habe: Wieso bekomme ich bei ein und derselben Seite mal den richtigen Quellcode und mal noch ein paar fehlerhafte Zeichen dazu?

    Was nun? Hast du es mit meiner recv-Funktion versucht oder mit der, die du davor hattest? (btw glaub ich dir nicht, dass du die so in nem Buch gefunden hast...)
    Falls du noch immer die offensichtlich falsche Methode (kam ja nun schon von mind. 3 Leuten), dann solltest du evtl mal nachdenken, ob du verstanden hast, was deine Funktion macht und vll doch mal die Beiträge lesen...

    Zum const-Umgang:

    Sinthoras schrieb:

    Ich dachte, ich sage dem Compiler damit nur, dass meine Methode das Objekt nicht ändert. Nicht?

    Prinzipiell schon...
    Aber ich halte so etwas auch für sehr sinnvoll:

    hustbaer schrieb:

    Anders gesagt: const sollten IMO nur Dinge sein, bei denen es keine Rolle spielt ob man sie wiederholt, oder ganz weglässt (ganz weglassen geht natürlich nur sofern man das Ergebnis nicht auswertet). Und bei send/recv/close/... auf einen Socket ist das ja ganz sicher nicht gegeben.

    Hat hustbaer eigtl schon alles dazu gesagt...

    bb



  • Dieser Thread wurde von Moderator/in Phoemuex aus dem Forum C++ in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • diagnostiker schrieb:

    Sinthoras schrieb:

    Davon ab: Weiß vielleicht doch jemand, warum der Quelltext mal richtig, mal falsch geladen wird?

    steht doch schon da oben: du liest MAXRECV bytes ein und hast dann keine abschließende 0 mehr. beim anhängen an den string hängts dann vom zufall ab, wo der string terminiert wird (nämlich bei der ersten zufällig gefundenen 0 im speicher hinter dem string).

    versuch doch mal mit

    status = ::recv(m_sock, buf, MAXRECV - 1, 0);
    

    dann wird die 0 auch nicht überschrieben.

    Danke. Das Problem hatte ich davor nicht verstanden. Jetzt schon, danke.

    unskilled schrieb:

    btw glaub ich dir nicht, dass du die so in nem Buch gefunden hast...

    Darfst du getrost glauben. Ausgedacht hab ich's mir nicht, sonst hätte ich mir schon überlegt, was das soll...
    (J. Wolf, C++ von A bis Z, S.926 u. S.928 ff.)

    Hab den Fehler jetzt behoben und ich denke, es geht jetzt.
    Vielen Dank an alle, die mir geholfen haben.

    LG
    Sinthoras



  • Sinthoras schrieb:

    (J. Wolf, C++ von A bis Z, S.926 u. S.928 ff.)

    dieses Buch ist als sehr schlechtes bekannt


Anmelden zum Antworten