Winsock - Datenempfang
-
Hallo,
es geht um ein kleines Spiel, welches im Netzwerk spielbar sein soll. Es werden also relativ häufig kleine Datensätze von ca. 4 - 20 Bytes versendet und hin und wieder längere Datensätze von bis zu 2048 (in diesen Fällen aber oft nicht mehr als 500) Bytes. Es werden beim Server und Client jeweils asynchrone Sockets verwendet.
Bisher läuft es prima, die meisten Datensätze kommen richtig an, allerdings kommt es manchmal vor, dass ein Datensatz kaputt ist (siehe unten).Hier mal die Daten, wie sie gesendet werden und ankommen:
/*gesendet*/ /*empfangen*/ ++++++++++++++++++++++++++++++++++++++++++++++++++ id: 2 id: 2 tankID: 1 tankID: 1 feindID: 7 feindID: 7 ++++++++++++++++++++++++++++++++++++++++++++++++++ id: 2 id: 2 tankID: 3 tankID: 3 feindID: 9 feindID: 9 ++++++++++++++++++++++++++++++++++++++++++++++++++ id: 2 id: 2 tankID: 3 tankID: -858993460 feindID: 9 feindID: -858993460 ++++++++++++++++++++++++++++++++++++++++++++++++++ id: 2 id: 3 //hier siehts aus, als hätte er die tankID des letzten Paketes tankID: 0 tankID: 9 //hier siehts aus, als hätte er die feindID des letzten Paketes feindID: 8 feindID: -858993460 schaden: 204 ++++++++++++++++++++++++++++++++++++++++++++++++++ id: 2 id: 2 tankID: 0 tankID: -858993460 feindID: 8 feindID: -858993460 ++++++++++++++++++++++++++++++++++++++++++++++++++ id: 2 id: 2 tankID: 4 tankID: 0 feindID: 6 feindID: 8 ++++++++++++++++++++++++++++++++++++++++++++++++++ id: 2 tankID: 4 feindID: 6 ++++++++++++++++++++++++++++++++++++++++++++++++++Ich sende bei einem Aufruf meiner senden Funktion immer erst einen integer, der die Art der Nachricht enthält. Danach wird das eigentliche Paket geschickt. Empfangen wird auf die gleiche Art und Weise.
Hier mal ein Auszug aus der Funktion zum Empfangen von Daten:
//Message ID zum Identifizieren der kommenden Nachricht int id = -1; //Message ID empfangen result = recv(wParam, (char *)&id, sizeof(id), 0); if(result == SOCKET_ERROR) { result = WSAGetLastError(); } //Ein neues Angriffsziel soll empfangen werden if(id == PAK_NEW_AIM) { PaketAim paket; result = recv(wParam, (char *)&paket, sizeof(paket), 0); if(result == SOCKET_ERROR) { result = WSAGetLastError(); } }Nun meine Frage: wie kommen diese Fehler zustande? Und wie bekomme ich die weg?
Bitte helft mir, denn ich sitze schon seit einer geraumen Zeit an dieser Sache und komme nicht klar damit...
Danke schon einmal im Voraus!
-
Hallo,
ich würde das Problem so lösen:
Zuerst erstellst du einen "buffer" wo du das ganze Packet reinspeicherst.
Danach überprüfst du ob das Packet was in dem Buffer ist überhaupt komplett ist.
(Also ob es ein gültiges packet ist).
Am besten legst du dir dafür eine fixe länge eines packets fest & eine packet id.
Vergleichst die ID & länge wenn ok dann die gewünschten sachen rauslesen.
Falls keine packet id oder länge auslesbar -> recv und daten am buffer hinzufügen solange bis ein gültiges packet vorhanden ist.Ich hoffe ich konnte dir helfen.
Mit freundlichen Grüßen,
-winsock-helper
-
Hallo nochmal,
das obige Problem habe ich mittlerweile anhand der Anleitung vom winsock-helper gelöst. Danke schon einmal dafür!
Leider habe ich aber weiterhin ein anderes Problem: Es werden manchmal Datensätze in schneller Abfolge hintereinander gesendet, es kommen aber nicht alle an (noch einmal zur Erinnerung, ich benutze asynchrone Sockets).
Meine Vermutung ist, dass durch den send() Befehl das Senden angestoßen wird (so als eine Art Impuls) und das Programm dann einfach weitermacht. Wird kurz danach der send() Befehl wieder aufgerufen und die Daten vom vorherigen send() Befehl sind aber noch nicht komplett versendet, so werden die neuen Datensätze einfach verworfen (so dass ich sie auch nicht empfangen kann auf der Gegenstelle). Kann das sein?
Wie funktioniert das Ganze "innen"? Nach meiner Theorie dürfte es in dem Fall ja keinen Buffer geben, in den jeder send() Befehl seinen Datensatz reinschiebt und das ganze dann irgendwann eventuell sogar zusammen versendet wird.... das kann ich mir aber irgendwie nicht vorstellen..
Weiß da jemand was genaues zu?

-
