[C++] Packets

11/01/2011 11:28 MrSm!th#16
Das weiß ich, aber afaik zeigt er doch, wenn man ihn nach der Größe fragt, auch die Grafikgrößeren miteingerechnet oder nicht?

Wieso sollte das zeitraubend sein? Lies sie doch einfach in einem aus.
11/01/2011 12:46 .Infinite#17
hab den Quelltext in eine Textdatei kopiert und die Größe nachgeguckt :P Das sind die Bilder mit Sicherheit nicht drin. Aber egal.

Ich habe bis jetzt Dateien immer Zeilenweise ausgelesen...

Code:
cachein.open("cache.txt", ios::in);
	while(!cachein.eof())
	{
		getline(cachein, line);
		response.append(line);
	}
Wie lese ich den das ganze File auf einmal aus?
11/01/2011 13:11 MrSm!th#18
Achso alles klar :D

Also wenn du es unbedingt mit dem C++ Standard machen willst, Filestreams bieten auch unformatiertes Lesen via ::read an.
Dann musst du dir halt mit seekg oder seekp oder wie auch immer die heißen ne eigene kleine GetFileSize Funktion bauen und liest die Daten in einem Rutsch in nen Buffer.

Oder du nutzt die GetFileSize aus der Win32 API :p Ich bevorzuge es dann auch, direkt ReadFile zu nutzen, aber das ist Ansichtssache.
11/01/2011 16:16 .Infinite#19
Ich habs jetzt so:

Code:
string packets::Receive()
{
	string response;
	char ReceivedBytes[1024];
	int BytesReceived = 1;
	char* buffer;

	ofstream cacheout;
	ifstream cachein;
	cacheout.open(CacheFile);

	while(BytesReceived > 0)
	{
		BytesReceived = recv(Socket, ReceivedBytes, sizeof(ReceivedBytes), 0);
		cacheout.write(ReceivedBytes, BytesReceived);
	}
	cacheout.close();

	cachein.open(CacheFile);
	size = FileSize(CacheFile);
	buffer = new char[size];
	cachein.read(buffer, size);
	DeleteFile(CacheFile);
	response.append(buffer);
	delete buffer;
	return response;
};
Code:
int packets::FileSize(const char* FileName)
{
	ifstream filein;
	filein.open(FileName);
	filein.seekg(0, ios::end);
	return filein.tellg();
}
Aber es dauert immer noch ewig... :( Ich habe gerade mal ein ganz kleine Seite aufgerufen. Bei der dauert es jetzt genau so lange. Ich verstehe es nicht mehr. Diese String Klasse ist ja mal unglaublich schlecht.
11/01/2011 17:46 MrSm!th#20
std::string ist sogar sehr gut.
Versuch es doch anstatt mit append einfach mal mit =.
Außerdem würde ich dem String schon vorher bekannt geben, wie groß er sein soll, das erleichtert es.

Also den den String erst später deklarieren und zwar so:

Code:
//getting FileSize
string Response(FileSize);
Response = ...
Ich versteh aber nicht wozu o.ô
Wenn du sowieso schon das File in einen char Buffer ausliest, gib doch direkt den aus.
11/01/2011 22:16 .Infinite#21
Mit Strings kann ich hinterher besser weiterarbeiten. Dann muss ich Funktionen wie find, replace, erase, swap etc. nicht selber schreiben :P

Ob ich = oder append nehme kommt aufs gleiche raus.

Ne Größe kann ich beim initialisieren eines Strings bei mir nicht angeben. Lediglich den Inhalt a la string hallo("hallo") oder string hallo (5, 'h')...
11/02/2011 01:51 MrSm!th#22
Es geht doch erstmal um die Ausgabe.

Afaik hat ein Browser eh nicht die ganze Zeit 100% des Sources im Speicher, dafür gibts ja Cachefiles.
Aber stimmt schon, für so ein paar tausend Zeichen ist es komisch, dass es so lange dauert.

Hast du denn nun eigentlich mal probiert, nur downzuloaden und nicht wieder aus dem File einzulesen?
Geht es dann eigentlich schneller? Dann wissen wir zumindest schonmal, obs nun an den Netzwerkfunktionen oder an std::string liegt.
std::string ist eigentlich verdammt gut optimiert.

Oh entschuldige, ich habe mich da bei der String-Klasse vertan :D

Allerdings bietet std::string die Möglichkeit, den String mit n Elementen zu erstellen und mit dem Zeichen c n mal vorzubelegen.

Also wäre es das gleiche Ergebnis, wenn du string response(FileSize, '\0'); schreibst.
11/02/2011 10:07 .Infinite#23
Habs jetzt gerade noch mal getestet... Das Zeitaufwendige ist das Empfangen. Der Rest läuft jetzt in unter 1 sek.

Bis das CacheFile fertig geschrieben ist dauert es gut 15 Sekunden. Da kann es eigentlich nur noch an der recv() Funktion liegen. Und da sehe ich nicht mehr viele Verbesserungsmöglichkeiten.
11/02/2011 11:05 MrSm!th#24
Ich kann mir auch nicht vorstellen, dass Webbrowser mehr als 1kb gleichzeitig laden.
Vielleicht hat es einfach mit deinem Request zu tun, vielleicht ist der schlecht aufgebaut.

Selbst mit der WinInet API habe ich Dateien schneller geladen und ich hab keine Ahnung, was Browser noch so alles für Netzwerkoptimierungen haben.
11/02/2011 11:49 .Infinite#25
Oh verdammt... Ich könnte heulen.

Das Problem war die ganze Zeit vor meiner Nase. 2 Änderungen im Packet und es funktioniert super. Sogar ohne das Cachen.

Hatte gedacht am Packet kann es nicht liegen, weil ich es 1:1 aus LiveHTTPHeaders übernommen hatte...

Hab im Packet die Zeile
Code:
Accept-Encoding: gzip, deflate\r\n
weggelassen und die Zeile

Code:
Connection: keep-alive\r\n
in
Code:
Connection: close\r\n
geändert.

Ersteres bewirkt, dass ich den Inhalt nun auch lesen kann. Letzteres, dass das Empfangen nun super schnell geht. Da muss ich mich wohl bei den Strings entschuldigen -.-

Trotzdem würde mich interessieren, warum es so ist. Muss ich die Verbindung irgendwie manuell schließen, damit es auch anders funktioniert?
Vor allem weil es ja etwas auffällig ist, wenn meine Packets etwas anders aussehen, als solche, die der Browser normalerweise sendet...
11/02/2011 13:16 MrSm!th#26
Achso, ich dachte es lag am Null-Terminator.
Encoding hatte ich nämlich auch im Sinn, da ich über Http nicht so fiel weiß, viel mir nur Chunked Encoding ein und das müsste ja immer noch lesbarer Text sein, nur halt aufgeteilt.
Klar, komprimiert ergibts nur Müll :D

Was mich wundert ist aber, dass Connection: close es beschleunigt.
Denn keep-alive sorgt ja nur dafür, dass der Server die Verbindung nicht schließt, wenn die Antwort gesendet wurde. Mit dem Senden der Antwort hat es ja eigentlich nichts zu tun :/
Vor allem weil ich selbst auch oft keep-alive nutze und das Problem nicht habe.
Und Browser nutzen afaik auch keep-alive, damit sie eben nicht immer wieder neu aufgebaut werden muss, was das Browsen beschleunigt, wenn man die Seite nicht oft wechselt.

Kann dir aber auch nicht sagen, warum das bei dir so ist.
11/02/2011 15:25 .Infinite#27
WSAGetLastError() meldet auch keinen Fehler. Ob mit oder ohne keep-alive.

€: Ich bin anscheinend nicht der einzige, der dieses Problem hat:

[Only registered and activated users can see links. Click Here To Register...]

Allerdings kommt mir die beschriebene Lösung etwas unschön vor...
11/02/2011 20:35 MrSm!th#28
Es wäre ja mal einen Versuch wert, sich den FF Source zu laden und die Netzwerkfunktionen mal anzusehen.

Die Methoden sind aber nicht unschön.

So wie ich das verstanden habe, wird ja sofort in den Buffer geschrieben, nur blockt recv halt, bis der Server Timeout meldet; anscheinend ist keep-alive nur für nonblocking Funktionen gedacht; ergibt auch Sinn. Was will man denn die Verbindung halten, wenn man eh die ganze Zeit im blocking Call festhängt.
Also kannst du einfach nonblocking Socket Funktionen nutzen und rufst recv halt immer wieder in einer Schleife auf.
Im Grunde kannst du dir so auch deine eigene Klasse für ein blocking Socket schreiben, die nicht blockt, wenn alles angekommen ist.

Aber so wie es da steht, ist es nunmal: Du kannst nur wissen, dass du fertig bist, wenn du entweder alle Chunks geladen hast oder die Größe aus Content-Length erreicht ist.
Wird weder Chunked Encoding genutzt noch die Größe angegeben, musst du halt empfangen, bis du nichts mehr bekommst (und dann selbst mit nem kleinen Timeout arbeiten, da manchmal ja auch die Verbindung schlechter sein kann).

Dann musst du aber daran denken, dass du die Verbindung noch schließen musst.

Oder du machst es halt eben immer mit Connection: close.
Sollte bei nem Bot nicht so tragisch sein, da die ja meistens für Browsergames o.Ä. sind und man da eh nicht 100 mal in der Sekunde etwas klicken muss.
11/02/2011 23:48 .Infinite#29
Vielen Dank für die Hilfe! Echt super :handsdown:

Ich machs jetzt immer mit "Connection: close" und connecte danach jedesmal wieder.

Die richtige Arbeit kommt ja jetzt erst... Packets suchen, analysieren, nachbauen usw. :D

Das Problem wäre damit auf jeden Fall erledigt.