如何在带有套接字(socket.io)的NodeJS中找到客户端的响应时间(延迟)?

FR6*_*FR6 21 latency websocket node.js socket.io

我正在尝试用NodeJS创建一个多人游戏,我想在客户端之间同步动作.

在客户端和服务器之间找到延迟(请求返回客户端的时间)的最佳方法是什么?

我的第一个想法是客户端#1可以发送带有请求的时间戳,所以当客户端#2将接收客户端#1的动作时,他将调整动作速度以消除请求的延迟.但问题是,两个客户端的系统日期时间可能不相同,因此不可能两个人知道客户端#1请求的卷轴延迟.

另一个解决方案是使用服务器的时间戳,但现在我怎么知道客户端的延迟?

Luk*_*uka 28

看完这些答案后...

……我还是不满意。我访问了官方文档,好吧,好吧 - 解决方案已经内置了。

你只需要实现它——看看我的:

客户

// (Connect to socket).

var latency = 0;

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

    console.log(latency);
});

// Do cool things, knowing the latency...
Run Code Online (Sandbox Code Playgroud)

 服务器

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});
Run Code Online (Sandbox Code Playgroud)

  • 这是最好也是最简单的答案。 (3认同)
  • 请注意,socket.io v3.0 中已弃用“pong”。更多信息[此处](https://socket.io/docs/v3/migration-from-2-x-to-3-0/#No-more-%E2%80%9Cpong%E2%80%9D-事件检索延迟)。 (3认同)
  • @ItayGanor 帮我解决了头痛问题——谢谢 (2认同)

kan*_*aka 22

我将假设您正在使用WebSockets或Socket.IO,因为您正在实施一个延迟很重要的游戏(并且您将其标记为此类).

我认为服务器应该测量并跟踪每个客户端的这个.

您可能希望实现服务器可以请求客户端的某种ping操作.一旦客户端收到请求,它就会向服务器发回响应.然后服务器除以2并更新该客户端的延迟.您可能希望服务器定期对每个客户端执行此操作,并且可能对最后几个客户端进行平均,这样您就不会因突然但临时的峰值而出现奇怪的行为.

然后,当有来自一个客户端的消息需要发送(或广播)到另一个客户端时,服务器可以将client1的延迟添加到client2的延迟,并将此作为延迟偏移传递给client2作为消息的一部分.然后,client2将知道client1上的事件发生在很多毫秒之前.

在服务器上执行此操作的另一个原因是某些浏览器Javascript时间戳不准确:http://ejohn.org/blog/accuracy-of-javascript-time/.我怀疑node.js时间戳与V8(这是少数准确的时间之一)一样准确(或更多).

  • 是的我正在使用"socket.io".这正是我所实现的,我忘记的是将延迟除以2!谢谢你的建议! (3认同)

Sah*_*bov 20

概述:

建立socket.io连接后Date,在客户端上创建一个新对象,让我们调用它startTime.这是您向服务器发出请求之前的初始时间.然后,您ping从客户端发出一个事件.命名约定完全取决于您.同时服务器应该监听ping事件,当它收到事件时ping,它会立即发出pong事件.然后客户抓住该pong事件.此时您想要创建另一个表示的日期对象Date.now().所以此时你有两个日期对象 - 在向服务器发出请求之前的初始日期,以及在向服务器发出请求并且它回复之后的另一个日期对象.减去startTime当前时间,你就得到了latency.

客户

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);
});
Run Code Online (Sandbox Code Playgroud)

服务器

io.sockets.on('connection', function (socket) {
  socket.on('ping', function() {
    socket.emit('pong');
  });
});
Run Code Online (Sandbox Code Playgroud)

也可作为Github Gist使用.

  • 这会每2秒在"乒乓"上添加另一个回调.socket.on('pong'东西应该在setInterval之外. (2认同)
  • 对我来说,使用"ping"这个词不起作用.我认为它已经被node.js使用了.我把它改成了不同的东西而且很有效. (2认同)

Tor*_*amo 6

我通常做什么来发送带有请求的时间戳:

  1. 在客户端,创建一个new Date()并发timestamp: date.getTime()送到服务器,每个 JSON 请求。
  2. 在服务器上,收到请求后,将 aprocessed: (new Date()).getTime()放入对象中。
  3. 处理请求。
  4. 在响应中,放置timestamp来自请求和一个新的处理字段:processed: (new Date()).getTime() - req.processed现在包含处理请求所花费的毫秒数。
  5. 在客户端上,当收到响应时,取timestamp(与第 1 点发送的相同)并将其从当前时间中减去,再减去处理时间 ( processed),即以毫秒为单位的“真实”ping 时间。

我认为您应该始终在 ping 时间中包含请求和响应的时间,即使存在单向通信。这是因为这是“ping 时间”和“延迟”背后的标准含义。如果是单向通信并且延迟仅为实际 ping 时间的一半,那只是“好事”。