[C++] Packets

10/30/2011 12:29 .Infinite#1
Ich versuche gerade einen simplen Packetbot zu schreiben... Meine Funktion fürs Empfangen sieht momentan so aus:

Code:
void packets::Receive(stringstream &response)
{
	char ReceivedByte;
	while(recv(Socket, &ReceivedByte, 1, 0) > 0)
	{
		response << ReceivedByte;
	}
};
Nur leider dauert das Empfangen der Antwort auf eine simple GET Anfrage ca. 15 Sek. Lässt sich das irgendwie effizienter machen?
10/30/2011 13:44 ms​#2
Mehr als nur 1 Byte pro recv-Call holen.
10/30/2011 13:47 .Infinite#3
Aber wenn ich mir jetzt zb. immer 5 bytes hole, und von der Antwort fehlen nur noch 4 bytes. Dann wirft recv() einen Fehler und mir fehlen die letzten 4 byte oder?
10/30/2011 13:52 ms​#4
Der zurückgegebene Wert gibt an, wie viele Bytes angekommen sind. Das 3. Argument gibt nur an, wie viele Bytes maximal geholt werden sollen.
10/30/2011 15:15 .Infinite#5
Oh, da hab ich mich wohl vertan... Danke!
10/30/2011 18:55 MrSm!th#6
Du solltest aber den Fall bearbeiten, dass 0 Bytes empfangen wurden. Ein Rückgabewert von 0 bedeutet, dass die Verbindung geschlossen wurde.
10/30/2011 20:18 .Infinite#7
Der Fall wird doch mit der Schleife behandelt. Der Wert kann doch eig. nur gleich Null sein, wenn alle Daten übertragen würden und die Verbindung geschlossen wurde oder größer als 0(bzw. hier 1), wenn er noch am empfangen ist...

€: Habs jetzt mit mehreren Bytes(255 ist meine ich maximum) gemacht, bringt aber nichts. Ist genauso langsam wie vorher... Aber bei kurzen Antworten ist es unter einer Sekunde. Nur wenn ich ne komplette Seite Anfrage dauert es lange.
10/30/2011 21:25 MrSm!th#8
Dann mach halt bei ner kompletten Seite noch größere Abfragen.
Da kannst du ruhig ein ganzes KB abfragen bei Seiten mit 80+ KB.

Die Verbindung kann auch durch einen Fehler getrennt werden und dann solltest du richtig reagieren und nicht einfach das ganze als vollständige Antwort betrachten ;f
10/30/2011 22:31 .Infinite#9
Ich machs jetzt so:

Code:
string packets::Receive()
{
	string response;
	char ReceivedBytes[1024];
	while(recv(Socket, ReceivedBytes, sizeof(ReceivedBytes), 0) > 0)
	{
		response.append(ReceivedBytes);
	}
	return response;
};
Allerdings dauert es immer noch ewig...



Komisch ist jedoch, dass erst teilweise das Paket und dann nur noch zufällige Zeichenfolgen ankommen. Außerdem gibt die Konsole Piptöne aus. Das war vorher nicht...

€: Array nicht nullterminiert?
10/31/2011 00:12 MrSm!th#10
Du solltest es natürlich nicht einfach ausgeben.

Ein Http Packet hört mit einer Leerzeile auf, ob danach noch ein \0 Byte folgt, weiß ich nicht.

Häng halt sicherheitshalber immer eins dran.

Wie groß ist denn die Seite, die du lädst?
Du kannst es btw auch mit der WinInet Api machen.
10/31/2011 00:34 .Infinite#11
Warum nicht ausgeben?

Die Seite ist ca. 80kb groß.
10/31/2011 12:36 MrSm!th#12
Dann liegt es wohl einfach daran, dass du C++ nutzt und der String immer wieder verlängert werden muss.

Sicher, dass es 80kb ohne Bilder etc. sind?
10/31/2011 16:17 .Infinite#13
Jep. 84kb. Die Startseite von e*pvp...

Es liegt anscheinend tatsächlich daran, dass der String immer wieder verlängert werden muss. Wenn ich es sofort ausgebe klappts super schnell...
Gibt es also eine bessere Möglichkeit dafür? Ich kann ja schlecht ein 10MB großes char Array erstellen, in das die empfagenen Bytes verschoben werden.


€: dass nur Müll ankam lag an meinem Packet und daran, dass immer 1kb in response verschoben wurde, auch wenn weniger ankommt...

Jetzt sieht es also so aus:
Code:
string packets::Receive()
{
	string response;
	char ReceivedBytes[1024];
	int BytesReceived = 1;
	while(BytesReceived > 0)
	{
		BytesReceived = recv(Socket, ReceivedBytes, sizeof(ReceivedBytes), 0);
		if (BytesReceived < sizeof(ReceivedBytes))
		{
			response.append(ReceivedBytes, BytesReceived);
		}
		else
		{
			response.append(ReceivedBytes);
		}
	}
	return response;
};
11/01/2011 00:20 MrSm!th#14
Die Startseite von Epvp enthält auch Grafiken.

Ein Browser cached die Daten in nem File.
Das geht vermutlich schneller, als jedes mal den Speicher zu relozieren.
Am Ende kannst du ja alles wieder aus dem File in einen String laden, dann musst du nur einmal den Speicher allozieren.
11/01/2011 10:44 .Infinite#15
Ähh. Normalerweise ist es doch so, dass im Quelltext der Seite nur die Links zu den Bildern sind und nicht die Bilder selber.
Der Browser fragt dann jedes Bild seperat vom Server an. Aber ich brauche das ja nicht zu machen. Mich interessiert ja nur der Text...

Das mit dem Cachen ist ne gute Idee. Bin gerade dran, habe aber bis jetzt keine große Verbesserung erreicht, das Zeitraubende ist dann wieder, die Datei auszulesen (geht das auch nicht Zeilenweise?).