Reputation: 9063
We're sending a lot of data down a websocket (from a Node.js app to the web browser).
The data is binary data in the form of blobs
.
Occasionally, the end-user is on a poor connection - and in this case, we'd like to 'skip' messages (leave them out) and make sure we don't cram down more data than the user can receive.
On the server side, we have tried:
function sendBlob(blob, socket) {
console.log('socket.bufferedAmount: ' + socket.bufferedAmount); // Always zero
if (socket.bufferedAmount > 0) {
return; // Never called
}
socket.send(blob);
}
Unfortunately bufferedAmount
always returns zero.
Is this the right way to see how much data is being queued but not sent/received in websockets, or is there a better way to achieve this?
(Have also tried logging socket.bufferedAmount
on the client-side, but it also always returns zero).
Upvotes: 6
Views: 11512
Reputation: 91619
The socket.bufferedAmount
property that exists on clients (as well as the ws module for Node) is the amount of bytes that it itself has buffered, not the remote. That means socket.bufferedAmount
on the server means how many bytes that are waiting to be sent to the client, and for the client it is how many bytes are waiting to be sent to the server.
The reason you aren't getting any change in the property is that your network is probably indeed sufficient to deliver the data. If you actually want to see a difference in socket.bufferedAmount
, then try throttling your browser network access. This can be done with browser extensions or tools like NetLimiter.
If you want to throttle connections by skipping messages, you can think about creating some type of heartbeat system between the client and server. There are many ways you could do this, such as applying this function:
setInterval(function() {
if (socket.bufferedAmount == 0) {
socket.send('heartbeat');
}
}, 1000);
And then detecting missed heartbeats by counting the time interval. This is rather inefficient, but there's also other ways to do this such as responding to sent data from the server (although take into consideration that if you want to send a heartbeat when receiving data, the heartbeat itself might get throttled or other side effects).
An alternative solution would also be available if you were willing to switch to Socket.IO. It has a feature that allows you to send volatile messages, which are messages that are dropped if the client is busy or is not able to accept messages for any reason.
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);
});
});
Do note that Socket.IO will be heavier on your application, and doesn't use the native websocket protocol. It will utilize websockets when it is an option, but it is one of many transports. Socket.IO is built on Engine.IO, which uses a fork of the module you're currently using.
Upvotes: 14
Reputation: 1519
The readonly attribute bufferedAmount
represents the number of bytes of UTF-8 text that have been queued using send()
method.
And your case here shows that you are trying to access it on message received from server.
so the bufferedAmount
is not set.
Upvotes: 1