I'm trying to write a simple client/server implementation to transfer image data between a browser and node.js server using BinaryJS websockets.
Following the api examples I've come up with something that appears to work, however it seems to be leaking memory as the usage reported by 'top' for the node process continually increases.
I'm not very familiar with javascript debugging, but using nodetime it appears to me as though none of the objects created are being garbage collected.
My basic code is as follows:
Server:
var BinaryServer = require('binaryjs').BinaryServer;
var fs = require('fs');
var server = BinaryServer({port: 9000});
server.on('connection', function(client){
console.log('Connection');
client.on('stream', function(stream){
stream.on('data', function(data) {
var file = fs.createReadStream(data['path']);
client.send(file, {'target':data['target']});
});
});
});
Client:
var client = new BinaryClient('ws://example.com:9000');
var controlStream;
function loadImage(target, src) {
controlStream.write({'path':src, 'target':target});
}
client.on('open', function(){
controlStream = client.createStream();
});
client.on('stream', function(stream, meta){
var parts = [];
stream.on('data', function(data){
parts.push(data);
});
stream.on('end', function(){
$('#'+meta['target']+' img').attr('src', (window.URL || window.webkitURL).createObjectURL(new Blob(parts)));
});
});
My understanding is this: the client opens a connection to the server, then creates a stream for sending requests. Upon receiving data from this stream, the server opens a FileStream with the requested path and pipes the data through a new stream to the client. When this finishes, the client update a page element with the data.
What am I missing here?
This is a known (well, sort of) issue with .createReadStream(); Basically, it doesn't automatically release the resources as it should. Here's a modification to your script that should resolve the issue:
var BinaryServer = require('binaryjs').BinaryServer;
var fs = require('fs');
var server = BinaryServer({port: 9000});
server.on('connection', function(client){
console.log('Connection');
client.on('stream', function(stream){
var file; //Moved this so it's accessible to the 'end' handler
stream.on('data', function(data) {
file = fs.createReadStream(data['path']);
client.send(file, {'target':data['target']});
});
stream.on('end', function(){
if (file) file.destroy.bind(file); //Releases the handle and allows garbage collection
});
client.on('close', function(){
if (file) file.destroy.bind(file); //Releases the handle and allows garbage collection
});
});
});
If my understanding is correct, you want to send binary data from your clients (browsers) to your server (and not vice-versa ?), using streams with BinaryJS. If this is correct, then the code snippet you gave are not doing what you want.
Can you tell us more ?