我们正在通过 websocket 发送大量数据(从 Node.js 应用程序到网络浏览器)。
数据是blob
形式的二进制数据。
有时,最终用户的连接状况不佳 - 在这种情况下,我们希望“跳过”消息(将它们排除在外)并确保我们不会塞入超过用户可以接收的数据量.
在服务端,我们尝试过:
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 对您的应用程序来说会更重,并且不使用 native websocket 协议(protocol)。当它是一个选项时,它将使用 websockets,但它是许多传输之一。 Socket.IO 基于 Engine.IO 构建,它使用您当前使用的模块的分支。
关于javascript - 对 WebSockets 发送的数据进行速率限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18782179/