Envoyer un message à un client spécifique avec socket.io et noeud.js

je travaille avec socket.io et noeud.js et jusqu'à présent il semble assez bon, mais je ne sais pas comment envoyer un message du serveur à un client spécifique, quelque chose comme ceci:

client.send(message, receiverSessionId)

mais ni la méthode .send() ni la méthode .broadcast() ne semblent répondre à mes besoins.

ce que j'ai trouvé comme solution possible, c'est que la méthode .broadcast() accepte comme second paramètre un tableau de Sessionides auxquels ne pas envoyer le message, donc je pourrais passer un tableau avec tous les Sessionides connectés à ce moment-là au serveur, sauf celui que je souhaite envoyer le message, mais je pense qu'il doit y avoir une meilleure solution.

des idées?

161
demandé sur Lucio Paiva 2011-01-10 16:29:45

11 réponses

Eh bien, vous devez saisir le client pour cela (surprise), vous pouvez soit aller de la manière simple:

var io = io.listen(server);
io.clients[sessionID].send()

qui peut casser, je n'en doute pas, mais il est toujours une possibilité que io.clients pourrait être changé, donc utiliser ce qui précède avec prudence

ou vous gardez la trace des clients vous-même, donc vous les ajoutez à votre propre clients objet dans l'auditeur connection et les supprimez dans l'auditeur disconnect .

je voudrais utiliser le dernier, puisque selon votre application vous pourriez vouloir avoir plus d'état sur le pour les clients de toute façon, donc quelque chose comme clients[id] = {conn: clientConnect, data: {...}} pourrait faire le travail.

82
répondu Ivo Wetzel 2011-01-10 14:14:13

la réponse D'Ivo Wetzel ne semble pas valable dans Socket.io 0.9 anymore.

en bref, vous devez maintenant sauvegarder le socket.id et utiliser io.sockets.socket(savedSocketId).emit(...) pour lui envoyer des messages.

C'est comme ça que j'ai obtenu que ça fonctionne dans un noeud groupé.serveur js:

tout d'abord, vous devez définir Redis store comme le magasin afin que les messages puissent aller à travers les processus:

var express = require("express");
var redis = require("redis");
var sio = require("socket.io");

var client = redis.createClient()
var app = express.createServer();
var io = sio.listen(app);

io.set("store", new sio.RedisStore);


// In this example we have one master client socket 
// that receives messages from others.

io.sockets.on('connection', function(socket) {

  // Promote this socket as master
  socket.on("I'm the master", function() {

    // Save the socket id to Redis so that all processes can access it.
    client.set("mastersocket", socket.id, function(err) {
      if (err) throw err;
      console.log("Master socket is now" + socket.id);
    });
  });

  socket.on("message to master", function(msg) {

    // Fetch the socket id from Redis
    client.get("mastersocket", function(err, socketId) {
      if (err) throw err;
      io.sockets.socket(socketId).emit(msg);
    });
  });

});

j'ai omis le code de regroupement ici, parce qu'il fait ce plus encombré, mais il est facile d'ajouter. Il suffit de tout ajouter au Code des travailleurs. Plus de docs ici http://nodejs.org/api/cluster.html

160
répondu Epeli 2012-05-09 12:01:40

chaque socket rejoint une pièce avec un socket id pour un nom, donc vous pouvez juste

io.to(socket#id).emit('hey')

docs: http://socket.io/docs/rooms-and-namespaces/#default-room

Cheers

72
répondu Matic Kogovšek 2014-12-03 11:28:38

la solution la plus simple et la plus élégante

c'est aussi simple que:

client.emit("your message");

Et c'est tout.

mais comment? Donnez - moi un exemple

Ce dont nous avons besoin est en fait un exemple complet, et c'est ce qui suit. Ceci est testé avec la prise la plus récente.io version (2.0.3) et il utilise aussi Javascript moderne (que nous devrions tous utiliser maintenant).

l'exemple est composé de deux parties: un serveur et un client. Chaque fois qu'un client se connecte, il commence à recevoir du serveur un numéro de séquence périodique. Une nouvelle séquence est lancé pour chaque nouveau client, de sorte que le serveur doit suivre individuellement. C'est là que le "j'ai besoin d'envoyer un message à un client particulier" entre en jeu. Le code est très simple à comprendre. Nous allons voir ça.

Serveur

server.js

const
    io = require("socket.io"),
    server = io.listen(8000);

let
    sequenceNumberByClient = new Map();

// event fired every time a new client connects:
server.on("connection", (socket) => {
    console.info(`Client connected [id=${socket.id}]`);
    // initialize this client's sequence number
    sequenceNumberByClient.set(socket, 1);

    // when socket disconnects, remove it from the list:
    socket.on("disconnect", () => {
        sequenceNumberByClient.delete(socket);
        console.info(`Client gone [id=${socket.id}]`);
    });
});

// sends each client its current sequence number
setInterval(() => {
    for (const [client, sequenceNumber] of sequenceNumberByClient.entries()) {
        client.emit("seq-num", sequenceNumber);
        sequenceNumberByClient.set(client, sequenceNumber + 1);
    }
}, 1000);

le serveur commence l'écoute sur le port 8000 pour les connexions entrantes. Quand on arrive, il ajoute ce nouveau client à une carte pour qu'il puisse garder la trace de son numéro de séquence. Il écoute aussi l'événement disconnect de ce client, quand il le supprimera de la carte.

chaque seconde, une minuterie est allumée. Lorsqu'il le fait, le serveur parcourt la carte et envoie un message à chaque client avec son numéro de séquence actuel. Il incrémente et stocke le numéro de la carte. C'est tout ce qui est à lui. Facile comme bonjour.

Client

la partie client est encore plus simple. Il se connecte simplement au serveur et écoute le message seq-num , l'imprimant sur la console à chaque fois qu'il arrive.

client.js

const
    io = require("socket.io-client"),
    ioClient = io.connect("http://localhost:8000");

ioClient.on("seq-num", (msg) => console.info(msg));

suivant l'exemple

installer les bibliothèques nécessaires:

npm install socket.io
npm install socket.io-client

exécuter le serveur:

node server

ouvrir les autres fenêtres du terminal et générer autant de clients que vous voulez en exécutant:

node client

j'ai aussi préparé un gist avec le code complet ici .

67
répondu Lucio Paiva 2017-10-01 15:32:37

dans 1.0 vous devez utiliser:

io.sockets.connected[socketid].emit();
32
répondu PHPthinking 2018-02-27 16:37:33

vous pouvez utiliser

/ / envoyer un message uniquement à l'expéditeur-client

socket.emit('message', 'check this');

//ou vous pouvez l'envoyer à tous les auditeurs, y compris l'expéditeur

io.emit('message', 'check this');

//envoyer à tous les auditeurs à l'exception de l'expéditeur

socket.broadcast.emit('message', 'this is a message');

//ou vous pouvez l'envoyer à une chambre

socket.broadcast.to('chatroom').emit('message', 'this is the message to all');

21
répondu DecoderNT 2016-06-25 07:25:06

quelle que soit la version que nous utilisons si nous nous contentons de console.log () l'objet" io " que nous utilisons dans notre code nodejs côté serveur, [e.g. io.('connexion', function(socket) {...});], nous pouvons voir que " io " est juste un objet json et il y a beaucoup d'objets enfants où les objets socket id et socket sont stockés.

j'utilise socket.io version 1.3.5, btw.

si nous regardons dans l'objet io, il contient,

 sockets:
  { name: '/',
    server: [Circular],
    sockets: [ [Object], [Object] ],
    connected:
     { B5AC9w0sYmOGWe4fAAAA: [Object],
       'hWzf97fmU-TIwwzWAAAB': [Object] },

ici nous peut voir les socketids "B5AC9w0sYmOGWe4fAAAA" etc. Donc, on peut faire,

io.sockets.connected[socketid].emit();

encore une fois, lors d'une inspection plus poussée nous pouvons voir des segments comme,

 eio:
  { clients:
     { B5AC9w0sYmOGWe4fAAAA: [Object],
       'hWzf97fmU-TIwwzWAAAB': [Object] },

ainsi, nous pouvons récupérer une socket d'ici en faisant

io.eio.clients[socketid].emit();

aussi, sous moteur nous avons,

engine:
 { clients:
    { B5AC9w0sYmOGWe4fAAAA: [Object],
      'hWzf97fmU-TIwwzWAAAB': [Object] },

Donc, nous pouvons aussi écrire,

io.engine.clients[socketid].emit();

Donc, je crois que nous pouvons atteindre notre objectif dans l'une des 3 façons j'ai répertorié ci-dessus,

  1. io.socket.connected [socketid].émettre(); Ou
  2. io.eio.clients [socketid].émettre(); Ou
  3. io.moteur.clients [socketid].emit ();
12
répondu Suman Barick 2015-06-17 10:30:10

Vous pouvez le faire

sur le serveur.

global.io=require("socket.io")(server);

io.on("connection",function(client){
    console.log("client is ",client.id);
    //This is handle by current connected client 
    client.emit('messages',{hello:'world'})
    //This is handle by every client
    io.sockets.emit("data",{data:"This is handle by every client"})
    app1.saveSession(client.id)

    client.on("disconnect",function(){
        app1.deleteSession(client.id)
        console.log("client disconnected",client.id);
    })

})

    //And this is handle by particular client 
    var socketId=req.query.id
    if(io.sockets.connected[socketId]!=null) {
        io.sockets.connected[socketId].emit('particular User', {data: "Event response by particular user "});
    }

Et sur le client, il est très facile à manipuler.

var socket=io.connect("http://localhost:8080/")
    socket.on("messages",function(data){
        console.log("message is ",data);
        //alert(data)
    })
    socket.on("data",function(data){
        console.log("data is ",data);
        //alert(data)
    })

    socket.on("particular User",function(data){
        console.log("data from server ",data);
        //alert(data)
    })
10
répondu abhaygarg12493 2016-06-07 12:28:27

à partir de la version 1.4.5, assurez-vous de fournir un socketId correctement préfixé dans io.to(). Je prenais le socketId le Client s'est connecté pour déboguer et il était sans préfixe donc j'ai fini par chercher pour toujours jusqu'à ce que je découvre! Donc vous pourriez devoir le faire comme ceci si L'Id que vous avez n'est pas préfixé:

io.to('/#' + socketId).emit('myevent', {foo: 'bar'});
5
répondu risuch 2016-07-22 11:23:47

io.douilles.sockets [socket.id].emit ( ... ) a travaillé pour moi en v0.9

4
répondu aljosa 2014-02-01 12:09:02

Socket.IO vous permet de "namespace" vos sockets, ce qui signifie essentiellement assigner différents endpoints ou chemins.

cela pourrait aider: http://socket.io/docs/rooms-and-namespaces /

0
répondu Igor T. 2015-01-12 16:18:42