TCP Problem
-
Hallo Leute. Ich melde mich nach recht langer Zeit nochmal.
Ich möchte direkt zur Sache kommen und nicht verschweigen, dass ich ein Problem hab, wo meine Intelligenz nicht mehr hin reicht.Nun, ich bin an einem Spiel am Programmieren was sich nun auch über Internet oder Netzwerk zu zweit spielen lässt. Es ist bis jetzt alles synchronisiert, läuft sogar recht schnell hat aber irgendwie ein Error.... wo meine Birne eindeutig zu klein für ist (Ich reg mich einfach drüber auf) >_<
Es geht nun darum, ich starte das Spiel bei mir zweimal und lasse mich zu mich selbst connecten - läuft alles einwandfrei und flüssig, kein einziges Problem keine Abweichung, echt klasse.
Nun das wirkliche Problem: Ich schicke das Programm zu jemanden, starte bei mir den Host und er connected zu mir. Erstmal läuft es flüssig, so als würde ich zu mir selber connecten. Der angezeigte Ping ist bis jetzt noch etwa 60 ms.
Nach einiger Zeit allerdings gibt es einen rießen lag und plötzlich schwangt der ping zwischen 0 ms und 600 ms. Also ein Programmdurchlauf 0 ms und der nächste Programmdurchlauf 600 ms.Um euch einen ungefähren einblick in die Programmstruktur zu geben folgender Pseudocode:
int latmax=7 // Die Anzahl der Programmdurchläufe, bis ein Synchronize erfolgt int latency=0 // Bei jedem Programmdurchlauf steigt dieser Wert um 1 Programmschleife: latency++ if (latency>latmax) { Spielereingabe() // Die Eingaben der Spieler z.b. Schuss werden abgefragt EingabenToString() // Alle eingaben werden in einen String zusammengefasst Synchronize() // Die jeweiligen String werden zum Stream geschickt, erst, wenn der String von der anderen Seite erhalten ist, läuft das Programm weiter. StringToEingabe() // Die Strings werden in die entsprechenden Eingaben für die Spieler zurücktransformiert und ausgewertet latency=0 } Hauptprogramm() // Alle möglichen Berechnungen wie z.b. Physik, Gegner KI, Grafik etc. springe zu ProgrammschleifeAls Test hab ich noch eine Ausgabe nach dem Auslesen des Strings gemacht.
Und zwar wird abgefragt, wieviele Bytes sich noch in dem Stream befinden.
Normalerweise wird ja immer ein string losgeschickt und dieser vom anderen ausgelesen, also wird als Byteanzahl nach dem Auslesen eine 0 ausgegeben - das trifft auch so zu bei dem Programm, wenn es normal läuft, wie es soll.
Nach dem rießen Lag kommt folgendes dabei raus:Programmdurchlauf 1 - Ausgabe 0
Programmdurchlauf 2 - Ausgabe 9
Programmdurchlauf 3 - Ausgabe 0
Programmdurchlauf 4 - Ausgabe 9
Programmdurchlauf 5 - Ausgabe 0
Programmdurchlauf 6 - Ausgabe 9Und so schwangt es immer weiter. Nun könnt ihr mir vielleicht ein wenig helfen?
Ich wäre SO dankbar, wirklich!!! Wenn noch Fragen oder Unverständlichkeiten sind, sagt es bitte....
-
mach nen counter der mitzaehlt welche synchronisation das gerade ist und vergleich mit dem counter der gegenseite, eventuell gibt es bei dir nen synch-fehler und dann laeufen deine systeme ein sync-frame auseinander.
normal hast du ja vermutlich sowas
func Synchronize() { seite 1 seite 2 sent sent wait wait //latenz recv recv }kommt nun eine seite aus dem takt hast du
func Synchronize() { seite 1 seite 2 sent wait recv sent sent wait //latenz wait recv }heisst also dass ein rechner wohl falsche daten bekamm und somit nicht mit dem empfangen aufgehoert hat (nein, kein tcp fehler sondern bei dir im code irgendwo vielleicht
) und deswegen wartet dann immer ein rechner im sync waehrend der andere das hauptprogramm ausfuehrt.wenn du das auf einem rechner reproduzieren moechtest, dann bau einen sleep vor recv ein (nicht hardcoden sondern random zwischen 40 und 80 oder so).
alternativ mach nen loopback ueber den anderen rechner und lass weiterhin zwei versionen auf deinem rechner laufen, dann kannst du vielleicht debuggen.es kann auch immer noch an irgendwas im netzwerk liegen z.b. dass daten gebuendelt werden statt halb leere 1520byte packete zu schicken (vielleicht ein smarter rooter/treiber)
versuch einfach mal ein padding auf 1520byte aufzubauen
-
So in etwa hab ich mir das schon gedacht, und ich hab es sogar einem namen gegeben: Doublewriting. Aber ok... mit dem Counter das ist eine Idee!
Ich werde es auf jeden fall versuchen.Edit: Ok Rapso, du hast vollkommen recht, ich habe einen Counter gemacht und es getestet. Die beiden Synchrotakte werden tatsächlich ganz genau durch diese Latenz
um etwa einen kompletten Takt phasenverschoben. Die Frage ist jetzt genau die, wie ich dagegen wirken könnte... ich könnte die beiden countwerte mit schicken und abfragen machen, ob der eigene Countwert höher ist. Wenn ja, dann wird gewartet bis die beiden wieder gleich sind.
Vielleicht gibt es aber doch noch eine bessere Möglichkeit, die man im Code ändern kann, hat jemand eine solche Idee?Nochwas: Zur Byterate pro Datenpaket, pro Synchronize schickt der Client 5 Bytes zum Host, der Host wird dann an jeden Spieler den string in ein Datenpaket schicken, wären bei 4 Mitspielern dann 20 Bytes pro Datenpaket...
-
Bigdeak schrieb:
Edit: Ok Rapso, du hast vollkommen recht, ich habe einen Counter gemacht und es getestet. Die beiden Synchrotakte werden tatsächlich ganz genau durch diese Latenz
um etwa einen kompletten Takt phasenverschoben. Die Frage ist jetzt genau die, wie ich dagegen wirken könnte...dazu muesstest du erstmal rausfinden wie das zustande kommt.
eventuell bei dir ein bug beim lesen der packete (falls du z.b. mal ne 0 am ende suchst und die nicht vorkommt, weshalb auch immer) oder es liegt an falscher benutzung von sockets, z.b. koennte es sein dass irgendwo mal ein timeout ist, du aber davon ausgehst dass die daten angekommen sind (vielleicht stecken ja im buffer in den du recv ja noch die daten vom letzten sync sodass dir das garnicht auffaellt. bau ueberall check ein ob die funktionen erfolgreich waren.