web-dev-qa-db-fra.com

socket.io - comment diffuser des messages sur un espace de noms?

Selon les exemples socket.io:

Pour diffuser, ajoutez simplement un indicateur broadcast aux appels de méthode emit et send. La diffusion signifie l'envoi d'un message à tout le monde, à l'exception du socket qui le démarre.

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.broadcast.emit('user connected');
});

J'ai essayé de combiner cela avec la nouvelle fonctionnalité de namsepace socket.io, alors j'ai obtenu ceci:

var chat = ioserver.of('/chat');

chat.on('connection', function (socket) {
      console.log('chat connection');   
      socket.on('message', function (msg) {
        console.log(msg);  
        chat.send(msg);
      });
  });

Cela fonctionne bien, tout le monde sur le canal de chat (et aucun autre canal) reçoit le message. Mais l'expéditeur l'obtient également. J'ai donc essayé de faire ce qui suit:

chat.on('connection', function (socket) {
      console.log('chat connection');   
      socket.on('message', function (msg) {
        console.log(msg);  
        chat.broadcast.send(msg);
      });
  });

et a obtenu une exception: "Impossible d'appeler la méthode" envoyer "de non défini". Ok, donc je pensais que cette diffusion est la caractéristique d'une seule prise (cela semble un peu étrange cependant - comment une seule prise peut être diffusée sur toutes les autres ...). J'ai donc essayé:

chat.on('connection', function (socket) {
      console.log('chat connection');   
      socket.on('message', function (msg) {
        console.log(msg);  
        socket.broadcast.send(msg);
      });
  });

mais maintenant c'était encore pire - personne n'a reçu le message, pas même l'expéditeur. Quoi qu'il en soit, c'est ce à quoi je m'attendais logiquement - une prise ne peut pas diffuser quelque chose par elle-même. Et sans exception cette fois, la diffusion est définie pour le socket.

Si je fais:

chat.on('connection', function (socket) {
      console.log('chat connection');   
      socket.on('message', function (msg) {
        console.log(msg);  
        socket.send(msg);
      });
  });

alors seul l'expéditeur d'origine reçoit le message, et c'est encore une fois assez logique - j'ai utilisé l '"envoi" du socket lié au client.

La question est donc: quelle est la bonne façon d'utiliser la fonction de diffusion?

Peut-être que le développeur de socket.io a fait une erreur et a ajouté la fonctionnalité de diffusion au mauvais objet (si je comprends bien, cela devrait être la fonctionnalité de l'espace de noms, mais maintenant elle n'est définie que pour la socket)?

48
JustAMartin

Il semble que j'ai pu résoudre ce problème par moi-même après avoir ouvert une prime. Désolé pour ça.

Quoi qu'il en soit, voyez si cela aide:

chat.on('connection', function (socket) {
  socket.on('message', function (msg) {
    socket.emit(msg); // Send message to sender
    socket.broadcast.emit(msg); // Send message to everyone BUT sender
  });
});

Cependant, vous pouvez économiser de la bande passante et créer une expérience plus rapide pour les utilisateurs si vous ne la renvoyez pas à l'expéditeur. Ajoutez simplement leurs messages directement au journal de discussion et utilisez éventuellement l'option auto-émettre uniquement pour confirmer qu'elle a été reçue sans problème.

70
Michael

Votre solution fonctionne si vous travaillez dans un environnement événementiel où les messages du client déclenchent une réponse à tous les autres, mais pas si vous souhaitez que le serveur envoie des messages à tous les clients.

Vous pouvez le faire en utilisant io.sockets.emit:

var io = require('socket.io').listen(80);
io.sockets.emit('message', { message: "Hello everyone!" });

Cependant, la documentation n'est pas claire sur la façon de procéder dans un espace de noms spécifique. io.sockets N'est qu'un raccourci vers io.of(''), en tant que tel, vous pouvez diffuser à tout le monde sur un espace de noms en appelant io.of('/namespace').emit:

var io = require('socket.io').listen(80);
io.of('/admins').emit('message', { message: "Hello admins!" });
36
Luca Spiller
var customNS = ioserver.of('/chat'); 

customNS.on('connection', function (socket) {
   socket.on('message', function (msg) {

       // Send message to sender 
       socket.emit(msg);

       // Send message to everyone on customNS INCLUDING sender
       customNS.emit(msg);

       // Send message to everyone on customNS BUT sender
       socket.broadcast.emit(msg);

       // Send message to everyone on ROOM chanel of customNS INCLUDING sender
       customNS.in('ROOM').emit(msg); 

       // Send message to everyone on ROOM chanel of customNS BUT sender
       socket.broadcast.in('ROOM').emit(msg); 


   });
});

vérifiez également cette réponse Envoyer une réponse à tous les clients sauf l'expéditeur (Socket.io)

28
smbeiragh

Peut-être que cela aidera quelqu'un

socket.broadcast.to('room1').emit('updatechat', 'SERVER', username + ' has connected to this room'); 

voir

Tutoriel Nodejs et Socketio Multiroom Chat

14
Shimon Doodkin