Wie kann ich die Antwortzeit (Latenz) von einem Client in NodeJS mit Buchsen (socket.io) finden?

StackOverflow https://stackoverflow.com/questions/4071258

Frage

Ich versuche, ein Multiplayer-Spiel mit NodeJS zu erstellen, und ich mag die Aktion zwischen Clients synchronisieren.

Was wäre der beste Weg, um die Latenzzeit (die Zeit, die ein Request an den Client zurück zu kommen) zu finden zwischen dem Client und dem Server?

Meine erste Idee war, dass der Client # 1 könnte einen Zeitstempel sendet mit Anforderung ist, so dass, wenn Client # 2 wird die Wirkung des Client # 1 empfängt er einstellen wird, ist Aktion Geschwindigkeit der Verzögerung der Anforderung zu entfernen. Aber das Problem ist, dass vielleicht das Systemdatum Zeit der beiden Kunden sind nicht identisch, so dass es nicht möglich ist, zwei wissen die Rolle Verzögerung auf Anforderung von Client # 1.

Die andere Lösung war den Zeitstempel des Servers zu verwenden, aber jetzt, wie kann ich wissen, die Latenzzeit eines Kunden?

War es hilfreich?

Lösung

Ich werde Sie verwenden WebSockets oder Socket.IO da man davon ausgehen, ein Spiel implementieren, wo Latenz Angelegenheiten (und Sie es als solche markiert).

Ich würde denken, sollte der Server wahrscheinlich messen und für jeden Kunden den Überblick über diese halten.

Sie wollen wahrscheinlich eine Art Ping-Aktion implementieren, dass der Server des Kunden anfordern kann. Sobald der Client die Anforderung empfängt, sendet er eine Antwort an den Server zurück. Der Server teilt dann durch 2 und aktualisiert die Latenz für diesen Client. Sie wollen wahrscheinlich der Server dies mit jedem Kunden regelmäßig zu tun und wahrscheinlich Durchschnitt der letzten, so dass Sie nicht seltsames Verhalten von plötzlichen, aber vorübergehenden Spitzen bekommen Sie.

Dann, wenn eine Nachricht von einem Client ist, dass der Bedarf an einem anderen Client gesendet (oder Broadcast) werden, kann der Server client1 Latenz zu client2 Latenz und kommuniziert dies als die Latenzzeit versetzt client2 als Teil der Nachricht hinzufügen. wissen client2 wird dann, dass die Veranstaltung auf client1 her, dass viele Millisekunden passiert ist.

Ein weiterer Grund, diese auf dem Server zu tun, ist, dass einige Browser Javascript Zeitstempel sind ungenau: http://ejohn.org/blog/accuracy-of-javascript-time/ . Ich vermute node.js Zeitstempel sind nur so genau (oder mehr so) als V8 (die eine der wenigen genau diejenigen ist).

Andere Tipps

Überblick:

Nach socket.io Verbindung hergestellt wurde, erstellen Sie ein neues Date Objekt auf dem Client, nennen sie es startTime. Das ist Ihre Anfangszeit , bevor Sie eine Anfrage an den Server zu machen. Sie emittieren dann ein ping Ereignis aus dem Client. Namenskonvention ist völlig Ihnen überlassen. Inzwischen Server sollte für ein ping Ereignis zuhören, und wenn er den ping empfängt, sendet sofort ein pong Ereignis. Client dann fängt das pong Ereignis. Zu diesem Zeitpunkt möchten Sie ein anderes Datum Objekt erstellen, die Date.now() darstellt. Deshalb an dieser Stelle haben Sie zwei Datumsobjekte - Anfangsdatum, bevor Sie eine Anfrage an den Server zu machen und ein anderes Datum, Objekt, nachdem Sie eine Anfrage an den Server, und es antwortete. Subtrahieren Sie die startTime aus der aktuellen Zeit und Sie haben die latency.

Client

var socket = io.connect('http://localhost');
var startTime;

setInterval(function() {
  startTime = Date.now();
  socket.emit('ping');
}, 2000);

socket.on('pong', function() {
  latency = Date.now() - startTime;
  console.log(latency);
});

Server

io.sockets.on('connection', function (socket) {
  socket.on('ping', function() {
    socket.emit('pong');
  });
});

Auch als Github Gist .

Was ich in der Regel tun mit Anfrage senden Zeitstempel:

  1. Auf dem Client erstellen new Date() und senden timestamp: date.getTime() an den Server, mit jeder JSON Anfrage.
  2. Auf dem Server auf den Empfang einer Anforderung, setzen Sie ein processed: (new Date()).getTime() im Objekt.
  3. Handle Anfrage.
  4. Auf der Antwort, legte den timestamp von der Anfrage, und ein neues verarbeitete Feld: processed: (new Date()).getTime() - req.processed dass nun die Anzahl der Millisekunden enthält es dauerte die Anforderung zu verarbeiten
  5. .
  6. Auf dem Client, wenn eine Antwort zu erhalten, nehmen Sie die timestamp (die die gleiche ist, die auf pt 1 gesendet wurde) und subtrahieren sie von der aktuellen Zeit und subtrahieren Verarbeitungszeit (processed), und es ist Ihre „echte“ Ping-Zeit in Millisekunden an.

Ich denke, Sie sollten immer die Zeit für beide Anfrage und Antwort in der Ping-Zeit beinhalten, auch wenn es eine Einweg-Kommunikation ist. Dies liegt daran, dass die Standard-Bedeutung hinter „Ping-Zeit“ und „Latenz“ ist. Und wenn es eine Einweg-Kommunikation und die Latenzzeit ist nur die Hälfte der realen Ping-Zeit, das ist nur eine „gute Sache“.

Nach all diesen Antworten lesen ...

... Ich war noch nicht zufrieden. Ich besuchte die offizielle Dokumentation und gut, gut, gut -. Die Lösung bereits eingebaut ist

Sie müssen nur zu ihrer Umsetzung - Check-out Mine:

Client

// (Connect to socket).

var latency = 0;

socket.on('pong', function(ms) {
    latency = ms;

    console.log(latency);
});

// Do cool things, knowing the latency...

Server

var server = require('http').Server(app);

// "socket.io": "^1.7.1"
// Set pingInterval to whatever you want - 'pong' gets emitted for you!
var io = require('socket.io')(server, {pingInterval: 5000});

Heres meine wirklich schnell und schmutzig Skript den Ping zu testen ... nur Kopf an http: // IhrServer: 8080 in Ihrem Browser und die Konsole (ssh Terminal für mich) sehen.

var http = require('http');
var io = require('socket.io');

server = http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'});
  res.write('<html>\n');
  res.write('  <head>\n');
  res.write('    <title>Node Ping</title>\n');
  res.write('    <script src="/socket.io/socket.io.js"></script>\n');
  res.write('    <script>\n');
  res.write('        var socket = new io.Socket();\n');
  res.write('        socket.on("connect",function(){ });\n');
  res.write('        socket.on("message",function(){ socket.send(1); });\n');
  res.write('        socket.connect();\n');
  res.write('    </script>\n');
  res.write('  </head>\n');
  res.write('  <body>\n');
  res.write('    <h1>Node Ping</h1>\n');
  res.write('  </body>\n');
  res.write('</html>\n');
  res.end();
});
server.listen(8080);

console.log('Server running at http://127.0.0.1:8080/');

var socket = io.listen(server);

socket.on('connection',function(client){
  var start = new Date().getTime();
  client.send(1);
  client.on('message',function(message){ client.send(1);  console.log( new Date$
  client.on('disconnect',function(){});
});

Ich bin sehr gespannt auf das, weil es scheint, wie meine Pings ziemlich hoch sind (200-400ms Hin- und Rückfahrt) auf große vps Boxen w / dedizierte Ressourcen sowohl in Kalifornien und New Jersey. (Ich bin an der Ostküste) Ich wette, Theres nur eine Menge Latenz auf den vps Boxen b / c sie so viel Verkehr dienen?

Die Sache, die mir bekommt ist, dass eine regelmäßige Ping aus dem Linux-Terminal von demselben Client auf dem gleichen Server ist 11ms im Durchschnitt um einen Faktor 10 niedriger ... bin ich etwas falsch oder ist etwas langsam mit node.js /socket.io/websockets?

Lesen Sie zuerst -. Durch wiederholte Fragen, warum das funktionieren soll, lassen Sie mich etwas klarstellen

  • Die Client-Callback-Funktion ist auf dem Client ausgeführt, , weshalb es den Zugang zum Verschluss hat, einschließlich der start Variable den Zeitstempel enthält. Dies ist die ack () Argument in socket.io.
  • Der Server kann natürlich nicht eine beliebige Funktion auf dem Client aufrufen und Zugriff auf die Schließung der Funktion. Aber socket.io ermöglicht einen Rückruf funtion zu definieren, die erscheint ausgeführt werden durch den Server, aber das ist eigentlich nur übergibt die Funktion Argumente über den Web-Buchse, und der Kunde ruft dann den Rückruf.

Was unten passiert (gehen Sie bitte den Beispielcode überprüfen!):

  1. Client speichert aktuelle Zeitstempel 1453213686429 in start
  2. Client sendet eine ping Ereignis an den Server und wartet auf eine Antwort
  3. Server antwortet auf das Ping-Ereignis mit „Bitte rufen Sie Ihren Rückruf mit leeren Argumenten“
  4. Client empfängt die Antwort und fordert clientCallback mit leeren Argumenten (Überprüfen Sie die Demo-Code, wenn Sie Argumente sehen wollen)
  5. clientCallback nimmt wieder den aktuellen Zeitstempel auf dem Client , z.B. 1453213686449, und weiß, dass 20 ms sind vergangen, seit er die Anfrage gesendet.

Stellen Sie sich die Druiden (Client) eine Stoppuhr halten und die Taste drücken, wenn der Bote (event) beginnt zu laufen, und es erneut drücken, wenn der Bote mit seinem Scroll kommt (Funktionsargumente) . Der Druide liest dann die Rolle und fügt die Zutat Namen zu seinen Trank Rezept und brüht den Trank. (Rückruf)

Okay, vergessen Sie den vorherigen Absatz, ich denke, Sie den Punkt.


Auch wenn die Frage bereits beantwortet wurde, hier eine kurze Einführung für die RTT mit socket.io Überprüfung:

Client

var start = Date.now();
this.socket.emit( 'ping', function clientCallback() {
    console.log( 'Websocket RTT: ' + (Date.now() - start) + ' ms' );
} );

Server

socket.on( 'ping', function ( fn ) {
    fn(); // Simply execute the callback on the client
} );

Demo-Code

Demo-Code als Knotenmodul: socketIO-callback.tgz Legen sie es auf und es mit

npm install
node callback.js

und wechseln Sie dann zu http: // localhost: 5060

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top