URL: https://www.overclockers.at/coding-stuff/c_http_download_81331/page_1 - zur Vollversion wechseln!
ich hab schon seit einiger zeit eine eigene klasse für http-downloads in verwendung. das problem dabei ist das es extrem cpu-belastend ist (bei ~120kB/s ca 20% auslastung @ >2ghz axp) da ich die sehr ineffiziente buffergröße von 1 byte verwende (recv (socket, buffer, 1, 0)). doch nur mit dieser war es mir möglich auch binäre dateien wie bilder, exe, zip usw fehlerfrei zu übertragen.
dann hab ich die übertragung etwas verbessert indem ich je 100kbyte eingelesen hab, und dann erst die daten in den übergebenen buffer bzw die datei zu schreiben - jedoch ist dann das problem mit den nicht-text-dateien wieder aufgetreten.
ich bin mit meiner weisheit leider am ende und kann nur noch raten und herumprobieren, aber ich hoffe hier gibt es leute mit mehr erfahrung in dem bereich.
die letzte änderung mit dem buffer bringt mich allerdings auf den gedanken das das problem weniger beim empfang als beim weiterverarbeiten der daten liegt.
tia
einer der häufigsten fehler in so einem zusammenhang, ist das richtige zusammensetzen der datenblöck, entweder zwischendurch oder am schluß.
hast du zb bedacht, daß recv überhaupt nicht verpflichtet ist, dir den gesamten buffer vollzuschreiben, sondern dir im rückgabewert sagt, wieviel bytes es wirklich sind ?
weiters, könntest du ja mit speziell präparierten testdaten untersuchen, was für eine art von korruption stattfindet - da läßt womöglich rückschlüsse zu.
Zitat von atroxeiner der häufigsten fehler in so einem zusammenhang, ist das richtige zusammensetzen der datenblöck, entweder zwischendurch oder am schluß.
hast du zb bedacht, daß recv überhaupt nicht verpflichtet ist, dir den gesamten buffer vollzuschreiben, sondern dir im rückgabewert sagt, wieviel bytes es wirklich sind ?
Zitat von atroxweiters, könntest du ja mit speziell präparierten testdaten untersuchen, was für eine art von korruption stattfindet - da läßt womöglich rückschlüsse zu.
ab dem charachter 32 sind alle darstellbar, von jedem würde ich 64 oder 128 hintereinander schreiben
im hex-editor müsste sich dann sehr leicht unstimmigkeiten finden lassen, weil für gewöhnlich 16 bytes in einer zeile angezeigt werden.
für blocksize verwende irgendeine "krumme" größe zb eine primzahl.
soweit, so gut
jetzt hab ich es so gelöst: ich statte recv() mit einem angemesseneren buffer von 1460 byte aus und verarbeite dann die empfangenen daten byte für byte. das hält die cpu-belastung bei 0-2% und gewährleistet eine korrekte darstellung der daten.
ABER, irgend etwas scheine ich verbaut zu haben, da das testprogramm beim aufruf von PostQuitMessage(0) einen hübschen fehler produziert der mich etwas stutzig macht:
"Die Anweisung in "0x5501f104" verweist auf Speicher in "0x5501f104". Der Vorgang "read" konnte nicht auf dem Speicher durchgeführt werden."
was könnte diesen fehler verursachen?
Was machst du byteweise mit den empfangenen Daten?
Zu dem Fehler: Sieht so aus, als würde eine DLL angesprungen, die nicht mehr im Speicher ist. Hast du vergessen, irgendeinen Hook oder sowas freizugeben?
Zitat von thatWas machst du byteweise mit den empfangenen Daten?
das ist jedenfalls meine methode um jegliche formatierung durch direkte zuweisungen wie _x = ch zu vermeiden, für verbesserungsschläge bin ich offen.Code:zum verständnis meiner etwas willkürlichen namensgebung: ... [int] len = empfangene bytes ... [char*] ch = buffer für empfangene daten ... [char] recvBuffer = zwischenablage für das bearbeitete byte ... [string] _x = hierin werden die daten zusammengesetzt; wird im weiteren zum schreiben auf die platte bzw speicherung im speicher benutzt for (int a=0; a<len; ++a) { if (ch[a] != 0) recvBuffer = ch[a]; else recvBuffer = '\0'; _x += recvBuffer; }
Zitat von thatZu dem Fehler: Sieht so aus, als würde eine DLL angesprungen, die nicht mehr im Speicher ist. Hast du vergessen, irgendeinen Hook oder sowas freizugeben?
hab den fehler entdeckt!
folgendes war passiert:
beim herstellen der TCP-verbindung über den socket lege ich die größe des empfangsbuffers fest, und reserviere dementsprechend speicher: buffer = (char*) malloc (bufferSize);
so, nun downloade ich den http header mit einem buffer von 1 byte da sich so das ende des headers wesentlich unkomplizierter findet und bei den wenigen 100B die performance zu vernachlässigen ist. vor dem beginn des eigentlichen downloads erhöhe ich die buffergröße - dabei hab ich allerdings vergessen ein buffer = (char*) realloc (buffer, new_size); zu machen und somit war recv() zum abschuss freigegeben.
diesen fehler hab ich jetzt behoben und siehe da; schnell und zuverlässig
ein problem hab ich jetzt allerdings noch: wie breche ich einen laufenden download - zb wenn das programm beendet wird - sicher wieder ab? derzeit tritt dann beim beenden der gleiche fehler auf wie zuvor
du mußt einfach nur den socket schließen, und 'sicher' (also ohne dir pointer zusammenzuhauen, bzw auf ungültige daten zuzugreifen) aus der schleife aussteigen.
done. wunderbar
solved *stempel*
overclockers.at v4.thecommunity
© all rights reserved by overclockers.at 2000-2025