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?
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.
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
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
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 .
dans 1.0 vous devez utiliser:
io.sockets.connected[socketid].emit();
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');
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,
- io.socket.connected [socketid].émettre(); Ou
- io.eio.clients [socketid].émettre(); Ou
- io.moteur.clients [socketid].emit ();
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)
})
à 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'});
io.douilles.sockets [socket.id].emit ( ... ) a travaillé pour moi en v0.9
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 /