Timeout Problem - TCP - BNetEx | Verbindungsverlust

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

 

Myn

Betreff: Timeout Problem - TCP - BNetEx | Verbindungsverlust

BeitragSa, März 30, 2013 23:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey!

der ein oder andere weiß vielleicht durch den Worklog das ich an einem Multiplayer Spiel arbeite.

Mein Problem ist seit einiger Zeit das der Client ohne merkbaren Grund die Verbindung zum Server verliert.
Weder Client noch Server crashen oder spucken irgend eine Meldung im debug-build aus.

Ich verwende Vertex BNetEx und verbinde per TCP.

Meine Frage wäre wie / warum Timeouts auftreten können. (SetTimeouts hat die Sache auch nicht verbessert, mit Werten > 20 hats angefangen zu laggen )

Zusatz: Mir ist aufgefallen das Timeouts meisten (immer?) auftreten wenn der Client auch Daten zum Server sendet. Lässt man den Client ohne Eingaben so dass wenig bis kein Upload vorhanden ist gibt es keine Fehler.

Sobald man läuft oder ander Aktionen mit Upload macht geht das keine 5min gut.

Code: [AUSKLAPPEN]

If(clientStream.GetState()<>1)Then

        clientStream.close();Notify("Connection lost!");End
   
Else

   While(clientStream.RecvAvail())

      While( clientStream.RecvMsg() );Wend
                              
      If(clientStream.GetState()<>1)Then Exit   <-------------
                     
      If(clientStream.Size() > 0)Then

         While Not(clientStream.Eof())

                             (Daten auslesen..)



Ohne die Abfrage an dieser Stelle + Exit hängt sich der Client dort bevorzugt in eine Dauerschleife auf.
Mit dem 'Exit' fliegt er im nächsten Durchgang weiter oben bei

Code: [AUSKLAPPEN]
If(clientStream.GetState()<>1)Then

        clientStream.close();Notify("Connection lost!");End
   
Else


.. raus.



Ich wüsste nicht was ich sonst noch für Code-Ausschnitte posten könnte, wie gesagt ich habe keine Ahnung woher dieser Fehler kommt.

Wenn jemand auch nur einen winzigen Ansatz für das Problem hat bitte antworten Smile
 

Myn

BeitragMo, Apr 01, 2013 12:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Ok, ich mir gestern mal die Arbeit gemacht und das komplette Netzwerksystem eigenständig extern zum laufen gebracht. Als Test habe ich dann den client an den Server & wieder zurück ein Packet senden lassen. Um genau zu sein ~100 Packte die Sekunde was deutlich mehr wie ist wie normal vom Spiel.

Dabei gab es bei 25 Clients (getestet auch über Internet) KEINE Fehler. Also liegt es nicht direkt am Netzwerksystem.

Da ich aus den letzten Monate von ~ jeder Woche ein Backup vom gesamten Projekt besitze werde ich nun alte Serverversionen ausprobieren und hoffen das ich damit den Fehler eingrenzen kann..
 

Myn

BeitragDi, Apr 02, 2013 17:01
Antworten mit Zitat
Benutzer-Profile anzeigen
Also grob gesagt, ich bin keinen Schritt weitergekommen.
So weit es möglich war alte Versionen in die Tests mit einzubeziehen haben sie alle gezeigt das diese Timeouts überall auftreten.

Ich habe nicht die geringste Ahnung wie diese zustande kommen und wäre für jeden Tipp dankbar ^^

-----------------------------------------------------------------------------------------------------------
Falls jemand wirklich Ahnung von BlitzMax hat und auch schonmal was mit Netzwerkprogrammierung gemacht (wie gesagt verwende TCP + BNetEx) wäre ich auch von einer Fernwartung über TeamViewer nicht abgeneigt.
Alternativ könnte ich auch namenhaften Leuten hier im Forum den Code schicken.
-----------------------------------------------------------------------------------------------------------

So komme ich jedenfalls nicht wirklich weiter Smile

Xeres

Moderator

BeitragDi, Apr 02, 2013 18:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Dann ist jetzt auch mit dem Multi-posting Schluss: Wenn sich niemand meldet, wird dir keiner helfen können oder wollen.
Viel Erfolg dennoch.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

DAK

BeitragDi, Apr 02, 2013 19:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Mir ist jetzt aber doch noch eine Idee gekommen: kann es sein, dass deine Internetverbindung hin und wieder Aussetzer macht? Wenn du z.B. Youtube-Videos anschaust, bleiben die oft einfach so beim Laden stecken (so auf die Art, laden eigentlich eh schnell, nur dann geht's auf ein mal auch Minutenlang kein bisschen weiter)?

In dem Fall kannst du mit deinem Programm nicht viel verbessern, bestenfalls schauen, dass du nach einem Timeout sofort wiederverbindest und die Verbindung erst dann als gekappt ansiehst, wenn zwei Reconnects gescheitert sind.
Gewinner der 6. und der 68. BlitzCodeCompo
 

Myn

BeitragDi, Apr 02, 2013 19:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Das wäre doch zu einfach Very Happy

Der besagte Fehler erscheint auch bei anderen die über eine 100k sowie 30k DSL Anbindung verfügen. (bei mir wäre das 6k DSL) Außerdem sollte es wenn man das ganze lokal (127.0.0.1) testet ja dann funktionieren - was eben auch nicht der Fall ist.


EDIT:

Nach weiteren Tests wo ich mir ausgegeben habe ab welcher Zeile die Verbindung wegbricht kann ich beim Client sagen das es die folgende ist:

Code: [AUSKLAPPEN]
While( clientStream.RecvMsg() );Wend


Danach ist GetState <> 1

DAK

BeitragMi, Apr 03, 2013 13:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Hast du schon versucht einen Test Case zu schreiben, also ein Programm, dass aus nichts besteht, als aus den zu testenden Zeilen?

Probier mal die Samples aus, die es zu der Lib gibt, ob es bei denen auch Probleme macht.

Wegen der Verbindung: ich hab hier zuhause eine 32mbit Glasfaserleitung und hab das gleiche Problem, was ich oben beschrieben habe. Das liegt nicht an der Geschwindigkeit, sondern an der Qualität der Verbindung.
Du hast aber recht, theoretisch sollte das Problem auf 127.0.0.1 nicht mehr auftreten. Probier aber dazu noch eine Sache: kappe alle Internetverbindungen, die dein Computer besitzt (WLAN aus, LAN-Kabel raus, alle VPNs zu und so weiter. Am besten alle Netzwerkadapter deaktivieren) und probier's dann auf 127.0.0.1. Dann rennt es nicht über Hardware sondern nur über Software, dann kannst du die Internetverbindung fix ausschließen.
Gewinner der 6. und der 68. BlitzCodeCompo
 

Myn

BeitragMi, Apr 03, 2013 15:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe das Netzwerksystem bereits raus kopiert und eigenständig zum laufen gebracht.
Wenn man die beiden verbinden lässt laufen sie stabil - bisher jedenfalls nie die Verbindung verloren.

Wenn ich den richtigen GameClient verbinden lasse (zum "ausgebauten" Server) dann bekam er Gestern wenn
ich irgendwelche Daten gesendet habe auch irgendwann ein Timeout.

Der einzigste Unterschied zu den echten Gameserver und Client ist das diese die Schleife in der das Netzwerk arbeitet in einen Thread ausgeführt wird. (Bei meinen Testprogrammen nicht.)


Zitat:
Wegen der Verbindung: ich hab hier zuhause eine 32mbit Glasfaserleitung und hab das gleiche Problem, was ich oben beschrieben habe. Das liegt nicht an der Geschwindigkeit, sondern an der Qualität der Verbindung.
Du hast aber recht, theoretisch sollte das Problem auf 127.0.0.1 nicht mehr auftreten. Probier aber dazu noch eine Sache: kappe alle Internetverbindungen, die dein Computer besitzt (WLAN aus, LAN-Kabel raus, alle VPNs zu und so weiter. Am besten alle Netzwerkadapter deaktivieren) und probier's dann auf 127.0.0.1. Dann rennt es nicht über Hardware sondern nur über Software, dann kannst du die Internetverbindung fix ausschließen.


Es gab die selben Fehler bei diesem Test.

DAK

BeitragMi, Apr 03, 2013 17:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Okay, wie kommunizierst du zwischen dem Netzwerkthread und dem Main Thread?
In welchem der beiden Threads findet die ursprüngliche Initialisierung (Verbindungsaufbau usw.) statt?
Gewinner der 6. und der 68. BlitzCodeCompo
 

Myn

BeitragMi, Apr 03, 2013 18:01
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Initialisierung findet durch einen Funktionsaufruf im MainThread statt. Zu diesem Zeitpunkt gibt es den NetworkThread noch nicht. Danach wird dieser gestartet und übernimmt das empfangen & senden.

Meine Packete sind so aufgebaut das ich immer einen ganzen String sende (WriteLine) - auslese und diesen dann wieder in verschiedene Werte splitte.
Wenn etwas gesendet werden soll wird der String in eine Liste angehängt die wiederum vom NetworkThread dann
irgendwann abgearbeitet und gesendet wird. (Die String Objecte)

Ich stelle übrings sicher das nur vollständige und keine falschen Packete nach dem empfangen verarbeitet werden. Wie gesagt da gibt es ja sonst auch keine Probleme Wink

DAK

BeitragMi, Apr 03, 2013 20:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Könnte es sein, dass das Netzwerkmodul vielleicht irgendwie Threadabhängig oder nicht Threadsafe ist? Lager die Initialisierung eventuell in den Netzwerkthread aus.

Ansonsten kannst du auf Verbindungsverlust hald einfach reconnecten.
Gewinner der 6. und der 68. BlitzCodeCompo
 

Myn

BeitragDo, Apr 04, 2013 12:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Habe den Code gestern jemanden aus dem Forum geschickt und einen wirklichen Fehler konnte nicht direkt gefunden werden. Es wurde ein paar kleine Änderungen getroffen und die SetTimeouts(300, 300) Funktion gesetzt, was zwar zu gefühlten weniger gehäuften Verbindungsabbrüchen führt - aber es kommt trotzdem noch vor.

Auffällig ist das ein Ping vom Client -> Server -> Client über Internet dadurch bis zu 200 - 500 ms benötigt.

Code: [AUSKLAPPEN]

If(clientStream.RecvAvail())Then
            
   zeitmessen = MilliSecs()      
               
   If(clientStream.RecvMsg())then <---------------
                     
      zeitmessen = (MilliSecs()-zeitmessen);If(zeitmessen > 0)Then Print"zeitmessen="+zeitmessen
                     
      While Not clientStream.Eof()

                  .. Packet auslesen



Für die makierte Abrage braucht er lokal bis zu 10ms, über Internet deutlich mehr. Rein theoretisch list er damit ja auch nur eine Message immer aus, weshalb eine While Schleife mehr Sinn machen würde, nur das dann zu hohe Wartezeiten auftreten. Untersuche heute das Problem dort genauer...

@DAK:
Habe die Initialisierung auch in den Thread probeweise verlegt, ohne spürbaren Unterschied.
Das einfach reconnecten ist nicht so einfach weil der Server den Client dann wieder auf den aktuelle Stand bringen muss, also wird die Map wieder geladen und alle Spieler sowie NPCs erstellt. Das würde unschöne Ladebildschirme verursache im Spiel.

DAK

BeitragDo, Apr 04, 2013 12:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Kannst du einen "unechten" reconnect einbauen? Also, der Client verbindet sich und sagt dem Server "Hey, bin wieder da, brauchst mir nicht alles schicken, ich hab ja eh schon alles", worauf der Server das Map neusenden einfach überspringt.
Gewinner der 6. und der 68. BlitzCodeCompo
 

Hangman

BeitragDo, Apr 04, 2013 13:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Das nennt man dann Workaround.
Ich habe Berthold gebrochen.

DAK

BeitragDo, Apr 04, 2013 14:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Nur, dass auch ohne den Fehler soetwas in jedem Programm, dass was mit Netzwerk zutun hat, drinnen sein sollte.
Stell dir vor, bei jedem Netzwerkhänger würds dich aus dem Spiel oder gestreamten Film hauen. Das wär doch arg unangenehm, vorallem, wenn man eine schlechte Internetverbindung hat.
Gewinner der 6. und der 68. BlitzCodeCompo
 

Myn

BeitragFr, Apr 05, 2013 17:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja, ich arbeite immer noch drann. Zu dem Ansatz das der Ping vom Client -> Server -> Client bis zu 300ms dauerd habe ich nun bemerkt das dies nur der Fall ist wenn der Client in Welten mit NPCs sich befindet und durch die Bewegungsupdates ~ 5-10 Messages vom Server die Sekunde empfängt. In leeren Welten in denen nur selten Datenaustausch (laufen + Statuswert Regenerationen) ist der Ping bei 60ms, also recht normal.

Ich kann aber einfach nicht glauben das TCP bei dem doch recht niedrigen Datenaustausch schon so in die Kniee geht. Was sind denn 5 - 15 Narichten pro Sekunde ? Eigentlich wenig. Ein Freund sendet in Java über eine TCP
lib realtime positions änderungen ohne kleinste Laggs..?! (natürlich kann ich nicht sagen wie die lib dort intern arbeitet - aber ich finde das schon recht merkwürdig)

Ist es also denkbar das TCP hier wirklich nicht mehr schafft oder liegt es doch noch an Dingen wie das es z.B. in einem externen Thread arbeitet?

Ich versuche derzeit einen parallenen UDP Stream nur mit Nachrichten vom Server zum Client einzubauen um den TCP Stream zu entlasten. ( Shocked )

DAK

BeitragFr, Apr 05, 2013 22:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Jetzt wird mir einiges klarer.
Der Unterschied mit TCP und UDP ist ja, dass TCP garantiert, dass alle Nachrichten richtig und in der richtigen Reihenfolge ankommen. UDP tut das nicht. Sendest du viele TCP-Nachrichten (5 pro Sekunde zählen schon als viele), dann brauchst du im Hintergrund ewig viel Zeit zum checken, dass alles da ist und auch in der richtigen Reihenfolge (vor allem das mit der Reinenfolge braucht Zeit).

Wenn die Reihenfolge und die Garantie auf Empfang nicht so wichtig ist, aber die Zeit schon dann nimm UDP (Spielerpositionen, Audiokommunikation, Videostreaming usw).
Ist es wichtig, dass es ganz genau so ankommt, wie geschickt (Textnachrichten wie Chat, Email, Websiten, Downloads usw).
Nimmst du TCP und sendest viele einzelne Nachrichten, dann fasse sie zusammen (statt jedes Update für jede Einheitenposition einzeln zu senden, fasse sie alle zu einer großen Nachricht zusammen). Das solltest du sowieso so oft wie möglich machen, um den Overhead zu reduzieren (jede Nachricht bekommt Verwaltungsdaten von TCP, Internet Protocol (IP) und dem Transportlayer dazu, womit eine Nachricht gut auch mal 200 Bytes Overhead zusammensammelt. Ist jede Nachricht von dir nur 20 Byte groß, wird sie mit Overhead 220 Byte groß, hast also 1000% Overhead. Fasst du 100 Nachrichten zusammen, ist die Datei mit Overhead nur um 10% größer als die Nutzdaten.)

Also verwende am Besten sowohl eine TCP- als auch eine UDP-Verbindung, wobei du die TCP für ganz wichtige Sachen, wie Chatnachrichten oder Geldtransaktionen verwendest, und UDP für alles, was nach einer halben Sekunde sowieso wieder geupdated wird.

Alternativ kannst du auch alles per UPD machen, und bei den wichtigen Sachen den Client noch mal eine Bestätigung (z.B. Hashwert der Nachricht) an den Server zurück schicken, also den Check, den dir TCP automatisch macht, stattdessen per UDP manuell machen.
Gewinner der 6. und der 68. BlitzCodeCompo
  • Zuletzt bearbeitet von DAK am Fr, Apr 05, 2013 22:40, insgesamt einmal bearbeitet

BtbN

BeitragFr, Apr 05, 2013 22:38
Antworten mit Zitat
Benutzer-Profile anzeigen
TCP ist heute auch für realtime-daten absolut kein ding mehr. Quasi jedes heutige MMO setzt auf TCP only, und hat da, auch bei WESENTLICH mehr als 5 nachrichten pro sekunde, keinerlei probleme mit.
Wenn du bei so geringem durchsatz(außer deine 5 nachrichten sind natürlich so groß, dass sie die leitung schon auslasten) schon an grenzen stößt, stimmt was mit deiner implementierung nicht.

DAK

BeitragFr, Apr 05, 2013 22:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Touche. Ist wohl zu lange her, dass ich mich in die Netzwerkprotokolle eingearbeitet hab.
Gewinner der 6. und der 68. BlitzCodeCompo

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group