tutorial socket rooms example javascript node.js websocket socket.io server-side

javascript - rooms - socket.io example



Enviar mensaje a un cliente especĂ­fico con socket.io y node.js (11)

Estoy trabajando con socket.io y node.js y hasta ahora parece bastante bueno, pero no sé cómo enviar un mensaje desde el servidor a un cliente específico, algo como esto:

client.send(message, receiverSessionId)

Pero ni los .send() ni .broadcast() parecen satisfacer mi necesidad.

Lo que he encontrado como una posible solución, es que el método .broadcast() acepta como un segundo parámetro una matriz de SessionIds a la cual no se envía el mensaje, por lo que podría pasar una matriz con todos los SessionIds conectados en ese momento al servidor , excepto el que deseo enviar el mensaje, pero creo que debe haber una mejor solución.

¿Algunas ideas?


La solución más simple y elegante

Es tan fácil como:

client.emit("your message");

Y eso es.

¿Pero cómo? Dame un ejemplo

Lo que todos necesitamos es, de hecho, un ejemplo completo, y eso es lo que sigue. Esto se prueba con la versión más reciente de socket.io (2.0.3) y también está utilizando Javascript moderno (que todos deberíamos usar ahora).

El ejemplo se compone de dos partes: un servidor y un cliente. Cada vez que un cliente se conecta, comienza a recibir del servidor un número de secuencia periódica. Se inicia una nueva secuencia para cada cliente nuevo, por lo que el servidor debe realizar un seguimiento de ellos de forma individual. Ahí es donde entra en juego el "Necesito enviar un mensaje a un cliente en particular" . El código es muy simple de entender. Vamos a verlo.

Servidor

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);

El servidor comienza a escuchar en el puerto 8000 las conexiones entrantes. Cuando uno llega, agrega ese nuevo cliente a un mapa para que pueda hacer un seguimiento de su número de secuencia. También escucha el evento de disconnect ese cliente, cuando lo eliminará del mapa.

Cada segundo, se dispara un temporizador. Cuando lo hace, el servidor camina por el mapa y envía un mensaje a cada cliente con su número de secuencia actual. Luego lo incrementa y almacena el número en el mapa. Eso es todo lo que es eso. Pan comido.

Cliente

La parte del cliente es incluso más simple. Simplemente se conecta al servidor y escucha el mensaje seq-num , imprimiéndolo en la consola cada vez que llega.

client.js

const io = require("socket.io-client"), ioClient = io.connect("http://localhost:8000"); ioClient.on("seq-num", (msg) => console.info(msg));

Ejecutando el ejemplo

Instale las bibliotecas requeridas:

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

Ejecute el servidor:

node server

Abra otras ventanas de terminal y engendre tantos clientes como desee ejecutando:

node client

También preparé una esencia con el código completo here .


A partir de la versión 1.4.5, asegúrese de proporcionar un socketId correctamente prefijado en io.to (). ¡Estaba tomando el socketId que el cliente inició la depuración y no tenía prefijo, así que terminé buscando hasta que me enteré! Por lo tanto, puede que tenga que hacerlo así si el ID que tiene no está prefijado:

io.to(''/#'' + socketId).emit(''myevent'', {foo: ''bar''});


Bueno, tienes que agarrar al cliente por eso (sorpresa), puedes ir por el camino simple:

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

Lo cual puede romperse, casi lo dudo, pero siempre existe la posibilidad de que io.clients cambie, así que use lo anterior con precaución

O puede hacer un seguimiento de los clientes usted mismo, por lo tanto, los agrega a su objeto de clients en el oyente de connection y los elimina en el oyente de disconnect .

clients[id] = {conn: clientConnect, data: {...}} este último, ya que dependiendo de su aplicación, es posible que desee tener más estado en el para los clientes de todos modos, así que algo como clients[id] = {conn: clientConnect, data: {...}} podría hacer trabajo.


Cualquiera que sea la versión que estamos utilizando si solo console.log () el objeto "io" que usamos en nuestro código del nodo del lado del servidor, [por ejemplo, io.on (''connection'', function (socket) {...});] , podemos ver que "io" es solo un objeto json y hay muchos objetos secundarios donde se almacenan los objetos id y socket de socket.

Estoy usando socket.io versión 1.3.5, por cierto.

Si miramos en el objeto io, contiene,

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

aquí podemos ver los socketids "B5AC9w0sYmOGWe4fAAAA" etc. Así que, podemos hacer,

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

Nuevamente, en una inspección adicional podemos ver segmentos como,

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

Entonces, podemos recuperar un socket desde aquí haciendo

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

Además, en el motor tenemos,

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

Entonces, también podemos escribir,

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

Entonces, supongo que podemos lograr nuestro objetivo en cualquiera de las 3 formas que enumeré anteriormente,

  1. io.sockets.connected [socketid] .emit (); O
  2. io.eio.clients [socketid] .emit (); O
  3. io.engine.clients [socketid] .emit ();

En 1.0 debes usar:

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


La respuesta de Ivo Wetzel ya no parece válida en Socket.io 0.9.

En resumen, ahora debe guardar el socket.id y usar io.sockets.socket(savedSocketId).emit(...) para enviarle mensajes.

Así es como conseguí que esto funcionara en el servidor agrupado de Node.js:

Primero debe configurar la tienda Redis como la tienda para que los mensajes puedan pasar por procesos cruzados:

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); }); }); });

He omitido el código de clúster aquí, porque lo hace más desordenado, pero es trivial de agregar. Solo agregue todo al código de trabajador. Más documentos aquí http://nodejs.org/api/cluster.html


Puedes hacerlo

En el servidor

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 "}); }

Y en el cliente, es muy fácil de manejar.

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) })


Puedes usar

// enviar mensaje solo al remitente-cliente

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

// o puede enviarlo a todos los oyentes, incluido el remitente

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

// enviar a todos los oyentes, excepto el remitente

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

// o puede enviarlo a una habitación

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




io.sockets.sockets [socket.id] .emit (...) funcionó para mí en v0.9