nkzawa / socket.io-stream

Stream for Socket.IO
MIT License
612 stars 111 forks source link

Broadcast stream? #32

Open peteruithoven opened 10 years ago

peteruithoven commented 10 years ago

Is there anyway to broadcast the stream to all clients in a namespace or room? I'd like to do something like this:

var nsp = io.of('/user');
nsp.on('connection', function(socket) {
  // receive a image by a broadcasting client
  ss(socket).on('image', function(incomingStream, data) {
    debug("on image ",data);

    // send the image
    var outgoingStream = ss.createStream();
    // emit stream to only one socket
    //ss(consumerSocket).emit('image', outgoingStream, {name: data.name});
    // broadcast stream to all other clients in namespace
    ss(socket).broadcast('image', outgoingStream, {name: data.name});
    incomingStream.pipe(outgoingStream);
  });
});
peteruithoven commented 10 years ago

It is possible to collect all "consumer" sockets in an array, create a outgoing stream per consumer and pipe the stream to all consumers.

var nsp = io.of('/user');
nsp.on('connection', function(socket) {
  var query = socket.handshake.query;
  debug("/user new connection type: ",query.type);

  switch(query.type) {
    case "consumer":
      consumerSockets.push(socket);
      break;
  }
  debug("  consumerSockets.length: ",consumerSockets.length);

  // receive the image
  ss(socket).on('image', function(incomingStream, data) {
    debug("on image ",data);

    for(var i in consumerSockets) {
      var consumerSocket = consumerSockets[i];
      var outgoingStream = ss.createStream();
      ss(consumerSocket).emit('image', outgoingStream, {name: data.name});
      incomingStream.pipe(outgoingStream);
    }
  });
});

But the problem when you run multiple Node.js instances (clustering) is that you never have references to all client sockets. I've used my own Redis pub/sub library to talk to a specific client, but I'm not sure yet how to use that with streams, see: https://github.com/Automattic/socket.io/issues/1811

peteruithoven commented 10 years ago

Looking through the code I understand socket.io-stream sends chunks of the data using regular emit's. This means implementing a broadcast shouldn't be impossible. Then socket.io-redis would take care of the clustering challenge.

this.sio.emit(exports.event + '-write', id, chunk, encoding, callback);

From: https://github.com/nkzawa/socket.io-stream/blob/master/lib/socket.js#L151

nkzawa commented 10 years ago

Yeah, there is no way to do that for now, but I think we can implement that as you explain. Please keep the issue open.

celevra commented 9 years ago

you don't have to track the connected sockets you can use io.sockets.connected like this:

  ss(socket).on('file', function(incomingstream, data) {

    for(var i in io.sockets.connected) {
      //don't send the stream back to the initiator
      if (io.sockets.connected[i].id != socket.id)
      {
        var socketTo = io.sockets.connected[i]
        var outgoingstream = ss.createStream();
        ss(socketTo).emit('file', outgoingstream, data);
        incomingstream.pipe(outgoingstream);
      }
    }
  });
peteruithoven commented 9 years ago

@celevra You can't use properties like io.sockets.connected if you want to work clustered and you usually want to to handle scale.