[BCB] Server/Client Socket, Internetseite auslesen: CHUNKED



  • Hallo liebes Forum,

    habe mich nach großer Hilfe bei mehreren Problemen in diesem Board nun auch endlich registriert. Aber nun zu meinem aktuellen Problem:

    Ich bin gerade dabei ein Programm zu schreiben was mir einen bestimmten Quelltext von einer Seite ausliest. Schön und gut habe ich auch nen genialen Beitrag hier im Board (oder 'magazin') gefunden:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-169861.html

    Der mir das alles erklären konnte. Ich habs auch super geschafft bis mir der Server als HTTP Response auf einmal gesagt hat das er mir seine Seite nun gechunked schickt:

    Http Response:
    (...)
    HTTP 1.1 200 OK
    transfer-encoding: chunked
    (...)
    

    Doch hat der Server einfach nichts mehr weiter geschickt, sprich:

    17b2
    <html><body> textext
    

    habe ich bekommen doch dann hat er sich einfach Disconnected. Das heisst ich hab den kompletten 2. Chunk Nicht bekommen. Jetzt weiss ich nicht, was ich jetzt tuen soll, wenn ich mich neuverbinde und nochmal den Request sende bekommen ich die gleiche Antwort vom Server.

    Ich hoffe ihr wisst was ich meine, und könnt mir helfen,

    Vielen Dank,
    squint 🙂



  • Bist du sicher, dass du die Verbindung nicht womöglich selbst beendest oder zumindest die Daten nicht empfängst/verarbeitest?
    Ansonsten könntest du die getestete Internetseite angeben, damit man das mal überprüfen kann. Wenn's bei uns funktioniert, müsstest du mal deinen Code posten.



  • Ich bin mir komplett sicher, alles was rein UNR raus geht wird mir direkt ausgegeben. Außerdem wird mir sofort ausgegebn wenn der server disconnected.

    der gibt mir auch nicht die größe des nächsten Chunks an, sonder er hört einfach auf, und beendet die Verbindung (er überträgt 8095 zeichen).

    Da der Code so komplex ist, werde ich ein paar Code Segmente nur hochstellen, die die ich am wichtigsten halte:

    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    { 
    univ = Edit1->Text; 	//Universelle URL
    Form1->ClientSocket1->Host = univ;
    Form1->ClientSocket1->Active=true;	//Verbinden
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::ClientSocket1Connect(TObject *Sender,
          TCustomWinSocket *Socket)
    {
    header = "Host: "+Edit1->Text+"\r\n";
    header += "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 ( .NET CLR 3.5.30729)\r\n";
    header += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
    header += "Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
    header += "Accept-Encoding: identity\r\n";
    header += "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n";
    header += "Keep-Alive: 115\r\n";
    header += "Connection: keep-alive\r\n";
    
    //ausgabe wenn connected:
    
    Memo1->Lines->Add("Connected");
    
            univ = Edit1->Text;
            Senden(univ);
            // Hier wird dem Header noch ein paar infos hinzugefügt (wohin, refer,leere Line), der header it Völlig in Ordnung!
    
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::ClientSocket1Read(TObject *Sender,
          TCustomWinSocket *Socket)
    {
    //Alles gesendete Wird hier mir ausgegebn:
    
            buf=Socket->ReceiveText();
            Memo1->Lines->Add(buf);
    
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::ClientSocket1Disconnect(TObject *Sender,
          TCustomWinSocket *Socket)
    {
    // Ausgabe wenn Disconnect:
    Memo1->Lines->Add("DISCONNECT");
    }
    //---------------------------------------------------------------------------
    

    nach dem 1. Chunk disconnected der Client.
    Ich hoffe das beschleunigt die Lösungssuche,

    @EDIT: Im übrigen, der Server hat Apache.

    mfg,
    squint 🙂



  • Ist dein Empfangspuffer zufällig 8 KB groß?
    Ersetze auch mal keep-alive-Zeilen durch "Connection: close", vermutlich unterstützt dein Code das nicht (sollte aber nichts mit dem Problem zu tun haben).
    Ein potentielles Problem sehe ich bei Memo1->Lines->Add(buf), denn wenn in den empfangenen Daten ein Nullbyte vorkommt, endet die Ausgabe an dieser Stelle. Sollte in einer HTML-Seite aber eigentlich nicht vorkommen.

    Edit: gibt ReceiveText() einen AnsiString zurück? Haben diese eine Maximallänge?
    Empfange die Daten besser mit einem binären Receive und schreibe sie in eine Datei. Ich habe den Verdacht, dass sich dein Problem damit erledigt.



  • Hallo und Danke fuer die schnelle Antwort 🙂

    Also, ich habe mir das ganze nochmal angeschaut, und zwar steht in dem RESPONSE Header vom Server, als Größenangabe des 1. Chunks: 1f73 (HEX) entspricht der Zahl 8 051.

    Soo jetzt hab ich mal geguckt wie groß "buf" ist, buf ist 8 129 Zeichen lang, verglichen mit 8 051 Zeichen ist das garnichtmal so knapp, und mitkalkulieren muss man noch das man den Header nicht mit einbeziehen darf, womit ich mit sehr hoher Wahrscheinlichkeit sagen kann, dass der Chunk erfolgreich angekommen ist.

    Das Problem muss also leiider irgendwo anders liegen, aber ich danke dir auf jeden fall fuer deine Hilfe!

    mfg,

    squint 🙂



  • Hat den niemand sonst eine Idee woran es liegen könnte?

    gΓεετz,

    squint


  • Administrator

    Was ist buf ? Was ist ReceiveText ? Was speicherst du alles in buf ?
    Falls genügend ankommt, aber nicht genügend angezeigt wird, dann klingt das als erstes für mich, dass irgendwo eine ungewollte Nullterminierung stattfindet 😉

    Und zu deinem Code:
    Wäre es irgendwie nicht viel besser zu zeigen, wie du empfängst? Ich meine der Fehler tritt doch beim Empfangen auf, was sollen wir dann mit diesem Code, welcher fast nur die Interaktion mit dem User Interface zeigt? Mich würde der Code hinter ReceiveText interessieren.

    Grüssli



  • Hallo und Danke fuer deine Atnwort Dravere!

    buf ist ein String. Ansi String ReceiveText(); gibt nichts weiter zurück, als einen String, empfangen von dem ClientSocket. Die Funktion ist schon in der Borland C++ 2006 mitdrin, und normalerweise klappt sie auch super. (Vergleichbar mit " recv() ")

    Ich bin mir auch garnicht sicher ob das überhaupt ein Problem in der Funktion ReceiveText() ist, sonder das vielleicht irgendwie ich mich neuverbinden muss...

    Das eine Nullterminierung stattgefunden hat ist sehr unwahrscheinlich, denn wie schon gesagt ist buf nach dem Empfangen vom ClientSocket 8129 Zeichen groß, (getestet mit buf.length() ), und nach Angaben des Servers, der gesagt hat der gesendete Chunk wäre 8051 Zeichen groß, ist das ziemlich Nahe.

    buf.Length() - Header größe [e]asymp[/e] 8051
    

    Hoffentlich findet irgendjemand den Fehler oder hat sowas schonmal gelöst.

    @EDIT So da ihr nun alle auf "\0" in buf tippt, hab ich mir das mal angeschaut, kann also WOHL sein, nur was sucht ne Null terminierung in einer HTML Seite?

    So 2. Frage: Wie krieg ich die nullterm. wieder weg; ^^

    mfg,

    squint 🙂


  • Administrator

    Squint schrieb:

    buf ist ein String. Ansi String ReceiveText(); gibt nichts weiter zurück, als einen String, empfangen von dem ClientSocket. Die Funktion ist schon in der Borland C++ 2006 mitdrin, und normalerweise klappt sie auch super. (Vergleichbar mit " recv() ")

    Du befindest dich hier aber im Standard C++ Forum, erwarte also nicht, dass jemand weiss, was diese Funktion tut. Ich habe nämlich keine Ahnung und finde auf die Schnelle auch keine Dokumentation dazu. Ich programmiere nie in Borland oder mit der VCL.

    Squint schrieb:

    Das eine Nullterminierung stattgefunden hat ist sehr unwahrscheinlich, denn wie schon gesagt ist buf nach dem Empfangen vom ClientSocket 8129 Zeichen groß, (getestet mit buf.length() ), und nach Angaben des Servers, der gesagt hat der gesendete Chunk wäre 8051 Zeichen groß, ist das ziemlich Nahe.

    Das ist völlig egal. In einen std::string kann ich einen String speichern, welcher ausschliesslich aus Nullterminierungen besteht und 8129 Zeichen lang ist. Ich nehme mal an, dass der AnsiString von VCL sehr ähnlich funktioniert (übrigen auch kein Standard C++, also muss er auch nicht in diesem Forum bekannt sein). Solche Stringklassen speichern die Länge separat ab und sind somit nicht mehr von der Nullterminierung abhängig, bzw. eine Nullterminierung kann in ihnen ohne Problem auftreten. Wenn man dann allerdings mit C Schnittstellen kommuniziert, und man daraus wieder ein C String baut, dann kann es zu Problemen kommen.

    Squint schrieb:

    Hoffentlich findet irgendjemand den Fehler oder hat sowas schonmal gelöst.

    Recht unwahrscheinlich, da es ein sehr spezifischer Fehler ist. Der Fehler also in deinem geschriebenen Code liegt 😉

    Squint schrieb:

    @EDIT So da ihr nun alle auf "\0" in buf tippt, hab ich mir das mal angeschaut, kann also WOHL sein, nur was sucht ne Null terminierung in einer HTML Seite?

    Kommt darauf an, wie du die Sache einliest. Kann schon sein, dass da plötzlich irgendwo eine Nullterminierung reinrutscht.

    Squint schrieb:

    So 2. Frage: Wie krieg ich die nullterm. wieder weg;

    Es geht nicht darum, dass du sie danach wegkriegst, sondern dass sie gar nicht erst passiert. Ich brauche allerdings Informationen zu ReceiveText, sonst kann ich dir nicht weiterhelfen. Gut wäre auch ein kurzes, minimales und kompilierbares Beispiel, wo der Fehler auch auftritt.

    Grüssli


Anmelden zum Antworten