对WebSockets发送的数据进行速率限制

时间:2013-09-13 08:56:04

标签: javascript node.js websocket

我们在websocket上发送大量数据(从Node.js应用程序发送到Web浏览器)。

数据是blobs

形式的二进制数据

偶尔,最终用户连接不良 - 在这种情况下,我们希望'跳过'消息(将其留空),并确保我们不会填写比用户可以接收的数据更多的数据

在服务器端,我们尝试过:

function sendBlob(blob, socket) {
  console.log('socket.bufferedAmount: ' + socket.bufferedAmount); // Always zero

  if (socket.bufferedAmount > 0) {
    return; // Never called
  }

  socket.send(blob);
}

不幸的是bufferedAmount总是返回零。

这是查看排队数据但在websockets中没有发送/接收的数据的正确方法,还是有更好的方法来实现这一目标?

(还尝试在客户端记录socket.bufferedAmount,但它也总是返回零。)

2 个答案:

答案 0 :(得分:7)

客户端(以及节点的ws模块)上存在的socket.bufferedAmount属性是它自身缓冲的字节数,而不是远程。这意味着服务器上的socket.bufferedAmount表示等待发送到客户端的字节数,对于客户端,它是等待发送到服务器的字节数。

您没有对该属性进行任何更改的原因是您的网络可能确实足以提供数据。如果您确实希望在socket.bufferedAmount中看到差异,请尝试限制您的浏览器网络访问权限。这可以通过浏览器扩展程序或NetLimiter等工具完成。

如果要通过跳过消息来限制连接,可以考虑在客户端和服务器之间创建某种类型的心跳系统。有很多方法可以做到这一点,比如应用这个功能:

setInterval(function() {
  if (socket.bufferedAmount == 0) {
    socket.send('heartbeat');
  }
}, 1000);

然后通过计算时间间隔来检测错过的心跳。这是相当低效的,但还有其他方法可以做到这一点,例如响应从服务器发送的数据(尽管考虑到如果你想在接收数据时发送心跳,心跳本身可能会受到限制或其他副作用)

如果您愿意切换到Socket.IO,也可以使用替代解决方案。它具有允许您发送易失性消息的功能,这些消息是在客户端繁忙或因任何原因无法接受消息时丢弃的消息。

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  var timer = setInterval(function () {
    socket.volatile.emit('data', 'payload');
  }, 100);

  socket.on('disconnect', function () {
    clearInterval(timer);
  });
});

请注意,Socket.IO在您的应用程序上会更重,并且不使用本机websocket协议。当它是一个选项时它将使用websockets,但它是许多传输之一。 Socket.IO构建于Engine.IO之上,它使用您当前正在使用的模块的分支。

答案 1 :(得分:1)

readonly属性bufferedAmount表示使用send()方法排队的UTF-8文本的字节数。

此处的案例表明您正在尝试从服务器收到的消息中访问它。 所以bufferedAmount未设置。