tutorial socket rooms node example con node.js websocket socket.io latency

node.js - node - socket.io chat rooms example



¿Cómo puedo encontrar el tiempo de respuesta(latencia) de un cliente en NodeJS con sockets(socket.io)? (6)

Después de leer todas estas respuestas ...

... Todavía no estaba satisfecho. Visité los documentos oficiales y bueno, bueno, bueno, la solución ya está incorporada.

Solo necesitas implementarlo - mira el mío:

Cliente

// (Connect to socket). var latency = 0; socket.on(''pong'', function(ms) { latency = ms; console.log(latency); }); // Do cool things, knowing the latency...

Servidor

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});

Estoy intentando crear un juego multijugador con NodeJS y quiero sincronizar la acción entre clientes.

¿Cuál sería la mejor manera de encontrar la latencia (el tiempo que tarda una solicitud para regresar al cliente) entre el cliente y el servidor?

Mi primera idea fue que el cliente # 1 podría enviar una marca de tiempo con su solicitud, de modo que cuando el cliente # 2 reciba la acción del cliente # 1, ajustará su velocidad de acción para eliminar el retraso de la solicitud. Pero el problema es que tal vez la fecha y hora del sistema de los dos clientes no sean idénticas, por lo que no es posible que dos conozcan el retraso de la bobina en la solicitud del cliente # 1.

La otra solución fue utilizar la marca de tiempo del servidor, pero ahora, ¿cómo puedo saber la latencia de un cliente?


Visión general:

Una vez establecida la conexión socket.io, cree un nuevo objeto Date en el cliente, llamémoslo startTime . Este es su tiempo inicial antes de realizar una solicitud al servidor. A continuación, se emite un evento de ping desde el cliente. La convención de nombres depende totalmente de usted. Mientras tanto, el servidor debe estar escuchando un evento de ping , y cuando recibe el ping , emite inmediatamente un evento de pong . El cliente entonces atrapa el evento pong . En este momento, desea crear otro objeto de fecha que represente a Date.now() . Entonces, en este punto, tiene dos objetos de fecha: la fecha inicial antes de realizar una solicitud al servidor, y otro objeto de fecha después de realizar una solicitud al servidor y éste respondió. Reste el tiempo de startTime de la hora actual y tendrá la latency .

Cliente

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); });

Servidor

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

También disponible como Github Gist .


Aquí está mi script realmente rápido y sucio para probar el ping ... solo diríjase a http: // yourserver: 8080 en su navegador y mire la consola (ssh terminal para mí).

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(){}); });

Tengo mucha curiosidad sobre esto porque parece que mis pings son bastante altos (200-400 ms de ida y vuelta) en cajas grandes de vps con recursos dedicados tanto en California como en Nueva Jersey. (Estoy en la costa este) ¿Estoy apostando a que solo hay una gran cantidad de latencia en las cajas de vps b / c que están sirviendo tanto tráfico?

Lo que me molesta es que un ping regular desde el terminal de Linux desde el mismo cliente al mismo servidor es 11ms en promedio, un factor 10 más bajo ... estoy haciendo algo mal o algo lento con node.js / socket. io / websockets?


Lo que normalmente hago para enviar la marca de tiempo con solicitud:

  1. En el cliente, cree una new Date() y envíe la timestamp: date.getTime() al servidor, con cada solicitud JSON.
  2. En el servidor, al recibir una solicitud, coloque un processed: (new Date()).getTime() en el objeto.
  3. Manejar solicitud.
  4. En la respuesta, coloque la timestamp de timestamp de la solicitud y un nuevo campo procesado: processed: (new Date()).getTime() - req.processed que ahora contiene la cantidad de milisegundos que tomó para procesar la solicitud.
  5. En el cliente, al recibir una respuesta, tome la timestamp (que es la misma que se envió en el pt 1) y restájala de la hora actual, y reste el tiempo de procesamiento ( processed ), y está su tiempo de ping "real" en milisegundos.

Creo que siempre debe incluir el tiempo para la solicitud y la respuesta en el tiempo de ping, incluso si hay comunicación unidireccional. Esto se debe a que es el significado estándar detrás de "tiempo de ping" y "latencia". Y si se trata de una comunicación unidireccional y la latencia es solo la mitad del tiempo de ping real, eso es solo una "cosa buena".


Socket.IO que está utilizando WebSockets o Socket.IO ya que está implementando un juego donde la latencia es importante (y lo etiquetó como tal).

Creo que el servidor probablemente debería medir y hacer un seguimiento de esto para cada cliente.

Probablemente desee implementar algún tipo de acción de ping que el servidor pueda solicitar al cliente. Tan pronto como el cliente recibe la solicitud, envía una respuesta al servidor. El servidor se divide por 2 y actualiza la latencia para ese cliente. Probablemente desee que el servidor haga esto periódicamente con cada cliente y probablemente promueva los últimos para que no se produzcan comportamientos extraños de picos repentinos pero temporales.

Luego, cuando hay un mensaje de un cliente que debe enviarse (o difundirse) a otro cliente, el servidor puede agregar la latencia del cliente1 a la latencia del cliente2 y comunicarlo como compensación de latencia al cliente2 como parte del mensaje. client2 sabrá entonces que el evento en client1 sucedió hace muchos milisegundos.

Una razón adicional para hacer esto en el servidor es que algunas marcas de tiempo de JavaScript del navegador son inexactas: http://ejohn.org/blog/accuracy-of-javascript-time/ . Sospecho que las marcas de tiempo de node.js son tan precisas (o más) que V8 (que es una de las pocas precisas).


Lea primero. Debido a las preguntas repetidas sobre por qué se supone que esto funciona, déjeme aclarar un poco.

  • La función de devolución de llamada del cliente se ejecuta en el cliente, por lo que tiene acceso al cierre, incluida la variable de start que contiene la marca de tiempo. Este es el argumento ack () en socket.io.
  • El servidor, naturalmente, no puede llamar a una función arbitraria en el cliente y acceder al cierre de la función. Pero socket.io permite definir una función de devolución de llamada, que parece ser ejecutada por el servidor, pero esto simplemente pasa los argumentos de la función a través del socket web, y el cliente llama a la devolución de llamada.

¿Qué sucede a continuación (por favor verifique el código de ejemplo)?

  1. El cliente almacena la marca de tiempo actual 1453213686429 en el start
  2. El cliente envía un evento de ping al servidor y está esperando una respuesta
  3. El servidor responde al evento de ping con "Llame a su devolución de llamada con argumentos vacíos"
  4. El cliente recibe la respuesta y llama a clientCallback con argumentos vacíos (verifique el código de demostración si desea ver los argumentos)
  5. clientCallback nuevamente toma la marca de tiempo actual en el cliente , por ejemplo, 1453213686449 , y sabe que han pasado 20 ms desde que envió la solicitud.

Imagine al druida (cliente) sosteniendo un cronómetro y presionando el botón cuando el mensajero (evento) comienza a correr, y presionándolo nuevamente cuando el mensajero llega con su desplazamiento (argumentos de función) . El druida luego lee el pergamino y agrega los nombres de los ingredientes a su receta de poción y prepara la poción. (llamar de vuelta)

Está bien, olvida el párrafo anterior, supongo que tienes el punto.

Aunque la pregunta ya ha sido respondida, aquí hay una breve implementación para verificar el RTT con socket.io :

Cliente

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

Servidor

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

Código demo

Código de demostración como módulo de nodo: socketIO-callback.tgz y ejecútelo con

npm install node callback.js

y luego navega a http: // localhost: 5060