我们正在通过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
总是返回零。
这是查看有多少数据正在排队但未在 websocket 中发送/接收的正确方法,还是有更好的方法来实现这一点?
(也尝试过在客户端记录socket.bufferedAmount
,但它也总是返回零)。
客户端(以及 Node 的 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 构建,它使用您当前使用的模块的分支。
readonly 属性 bufferedAmount
表示已使用 send()
方法排队的 UTF-8 文本的字节数。
在此处的情况表明您正在尝试在从服务器收到的消息上访问它。所以没有设置bufferedAmount
。