4

我们正在通过 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在客户端登录,但它也总是返回零)。

4

2 回答 2

14

socket.bufferedAmount客户端(以及 Node 的ws模块)上存在的属性是它本身缓冲的字节数,而不是远程的。这意味着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 之上,它使用您当前使用的模块的一个分支。

于 2013-09-16T04:05:45.310 回答
1

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

您的案例表明您正试图在从服务器收到的消息上访问它。所以bufferedAmount没有设置。

于 2013-09-13T09:08:34.097 回答