Wie erhalte ich die Wartezeit zwischen Server und Client in C #?

7

Ich arbeite an einer C # Server-Anwendung für eine Game-Engine, die ich in ActionScript 3 schreibe. Ich verwende ein autoritatives Servermodell, um zu verhindern, dass betrogen wird, und faires Spiel zu gewährleisten. Bis jetzt läuft alles gut:

Wenn der Client sich bewegt, teilt er dem Server mit und beginnt mit dem lokalen Rendern. Der Server teilt dann allen anderen mit, dass der Client X angefangen hat, sich zu bewegen, unter anderem mit Details, damit sie auch mit dem Rendern beginnen können. Wenn der Client nicht mehr bewegt wird, teilt er dem Server mit, dass Berechnungen basierend auf der Zeit, zu der der Client die Bewegung verschoben hat, und dem Client die Tick-Verzögerung und Antworten an alle Benutzer ausführen, sodass sie mit den korrekten Werten aktualisiert werden können.

Die Sache ist, wenn ich die Standard-Tick-Verzögerung von 20 ms bei Serverberechnungen verwende, wenn der Client sich über eine ziemlich lange Strecke bewegt, gibt es eine merkliche Neigung nach vorne, wenn er anhält. Wenn ich die Verzögerung leicht auf 22ms erhöhe, läuft in meinem lokalen Netzwerk alles sehr flüssig, aber an anderen Orten ist die Neigung immer noch vorhanden. Nachdem ich ein wenig experimentiert habe, ist mir aufgefallen, dass die zusätzliche Verzögerung ziemlich stark von der Latenz zwischen Client und Server abhängt. Ich habe es sogar auf eine Formel gebracht, die ganz gut funktionieren würde: Verzögerung = 20 + (Latenz / 10).

Also, wie würde ich fortfahren, um die Latenz zwischen einem bestimmten Client und dem Server zu erhalten (ich verwende asynchrone Sockets). Der CPU-Aufwand kann nicht zu viel sein, um den Server nicht langsam laufen zu lassen. Ist dies wirklich der beste Weg, oder gibt es einen effizienteren / einfacheren Weg, dies zu tun?

    
DfKimera 21.04.2009, 03:54
quelle

5 Antworten

12

Entschuldigung, dass dies nicht direkt Ihre Frage beantwortet, aber generell sollten Sie sich nicht zu sehr auf die Messung der Latenz verlassen, da diese sehr variabel sein kann. Nicht nur das, Sie wissen nicht, ob die Ping-Zeit, die Sie messen, sogar symmetrisch ist, was wichtig ist. Es hat keinen Sinn, eine Latenzkorrektur von 10 ms anzuwenden, wenn sich herausstellt, dass die Ping-Zeit von 20 ms tatsächlich 19 ms vom Server zum Client und 1 ms vom Client zum Server beträgt. Die Latenz in den Anwendungsbedingungen ist nicht die gleiche wie im Netzwerk - Sie können möglicherweise eine bestimmte Maschine anpingen und eine Antwort in 20 ms erhalten, aber wenn Sie einen Server auf dieser Maschine kontaktieren, der nur 50 Mal pro Sekunde die Netzwerkeingabe verarbeitet Ihre Antworten werden um weitere 0 bis 20 ms verzögert, und dies wird ziemlich unvorhersehbar variieren.

Das ist nicht zu sagen, Latenzmessung es hat keinen Platz in Glättung Vorhersagen, aber es wird nicht Ihr Problem zu lösen, nur ein wenig aufräumen.

Auf den ersten Blick scheint hier das Problem zu bestehen, dass Sie in der ersten Nachricht Informationen gesendet haben, mit denen Sie die Daten bis zum Empfang der letzten Nachricht extrapolieren. Wenn alles andere konstant bleibt, gibt der in der ersten Nachricht angegebene Bewegungsvektor multipliziert mit der Zeit zwischen den Nachrichten dem Server die korrekte Endposition, in der sich der Client ungefähr befand (Latenzzeit / 2). Wenn sich die Wartezeit jedoch ändert, wird die Zeit zwischen den Nachrichten größer oder kleiner. Der Client weiß vielleicht, dass er 10 Einheiten bewegt hat, aber der Server hat ihn simuliert, als er 9 oder 11 Einheiten bewegt hat, bevor ihm gesagt wurde, dass er ihn auf 10 Einheiten zurücksetzen soll.

Die allgemeine Lösung dafür ist, nicht davon auszugehen, dass die Latenz konstant bleibt, sondern periodische Positionsaktualisierungen, die es dem Server ermöglichen, die Position des Kunden zu überprüfen und zu korrigieren. Mit nur 2 Nachrichten, wie Sie jetzt haben, wird der Fehler gefunden und nach der 2. Nachricht korrigiert. Bei mehr Meldungen wird der Fehler auf viele weitere Abtastpunkte verteilt, was eine glattere und weniger sichtbare Korrektur ermöglicht.

Es kann jedoch nie perfekt sein: Es braucht nur eine Verzögerung in der letzten Millisekunde der Bewegung und die Darstellung des Servers wird überschwingen. Sie können das nicht umgehen, wenn Sie zukünftige Bewegungen auf der Grundlage vergangener Ereignisse vorhersagen, da es keine echte Alternative zur Wahl zwischen korrekt - aber spät oder falsch - aber rechtzeitig gibt, da Informationen Zeit brauchen, um zu reisen. (Schuld Einstein.)

    
Kylotan 25.04.2009, 09:52
quelle
4

Eine Sache, die Sie bei der Verwendung von ICMP beachten sollten pings ist, dass Netzwerkgeräte oft ICMP-Verkehr niedrigere Priorität geben als normale Pakete, besonders wenn die Pakete Netzwerkgrenzen wie WAN überschreiten Links. Dies kann dazu führen, dass Pings gelöscht werden oder eine höhere Latenz aufweisen als der Datenverkehr tatsächlich auftritt und sich eher als Indikator für Probleme als als Messinstrument erweist.

Die zunehmende Nutzung von Quality of Service (QoS) in Netzwerken verschärft dies jedoch und in der Folge auch noch ping ist immer noch ein nützliches Werkzeug, es muss verstanden werden, dass es keine echte Reflektion der Netzwerklatenz für nicht-ICMP-basierten realen Verkehr ist.

Es gibt einen guten Beitrag auf dem Itrinegy Blog Wie misst man heutzutage die Latenz (RTT) in einem Netzwerk? dazu.

    
Sim 04.11.2009 03:09
quelle
4

Sie könnten den bereits verfügbaren Ping Klasse. Sollte gegenüber dem Schreiben Ihrer eigenen IMHO bevorzugt werden.

    
leen 25.04.2009 10:56
quelle
2

Haben Sie einen "ping" -Befehl, wo Sie eine Nachricht vom Server an den Client senden, dann Zeit, wie lange es dauert, um eine Antwort zu erhalten. Abgesehen von CPU-Überlastungsszenarien sollte es ziemlich zuverlässig sein. Um die Einweg-Reisezeit zu erhalten, teilen Sie die Zeit einfach durch 2.

    
Adam Robinson 21.04.2009 04:02
quelle
1

Wir können die Round-Trip Zeit unter Verwendung der Ping Klasse von das .NET Framework.

Instanziieren Sie eine Ping und abonnieren Sie die PingCompleted Ereignis:

%Vor%

Fügen Sie Code zum Konfigurieren hinzu und führen Sie den Ping aus.

Unser PingCompleted Event-Handler ( PingCompletedEventHandler ) hat eine PingCompletedEventArgs Argument. Das PingCompletedEventArgs.Reply wird abgerufen uns ein PingReply Objekt. PingReply.RoundtripTime gibt den Wert zurück Umlaufzeit (die Anzahl der Millisekunden, die zum Senden einer ICMP-Echoanforderung (Internet Control Message Protocol) und zum Empfangen der entsprechenden ICMP-Echoantwortnachricht benötigt werden):

%Vor%

Code-Dump eines voll funktionsfähigen Beispiels, basierend auf MSDN Beispiel . Ich habe es modifiziert, um die RTT auf die Konsole zu schreiben:

%Vor%

Vielleicht möchten Sie mehrere Pings durchführen und dann einen Durchschnitt berechnen, abhängig von Ihren Anforderungen.

    
Stephen Kennedy 12.03.2018 13:26
quelle