Enviar datos adicionales sobre la conexión del socket

80

¿Cuál es la mejor manera de enviar datos adicionales tras la conexión del socket?

Cliente:

socket.on('connect',function(){ 
//I'd like set some values and pass them up to the node server.
});

Servidor Node.js:

io.on('connection', function(client){
//I'd like to get the data here.
});

Por ejemplo, enviando un nombre de usuario o una dirección de correo electrónico, etc.

Dan
fuente

Respuestas:

66

Debe enviar sus datos en connect o en create:

var s = io('http://216.157.91.131:8080/', { query: "foo=bar" });
s.connect();

var c = io.connect('http://216.157.91.131:8080/', { query: "foo=bar" });

Con la nueva versión de socket.io , en el servidor es donde se han cambiado las cosas:

var io = require('socket.io')(server);

io.use(function(socket, next) {
  var handshakeData = socket.request;
  console.log("middleware:", handshakeData._query['foo']);
  next();
});
Miquel
fuente
He visto a otras personas decir que lo use socket.request.query, pero eso no me funciona en socket.io v1.7.2. Definitivamente tengo que usar socket.request._query.
Kellen
¿Por qué no hay documentación sobre esto? github.com/socketio/socket.io-client/blob/master/docs/…
rocketspacer
4
Para socket.io v1.7.3, tuve que usar socket.handshake.query(a través de esta respuesta ).
Galen Long
¿No hay forma de enviar más de un parámetro? ¿Alguien conoce la sintaxis? El ejemplo de Fox { query: "foo=bar", "bar=foo" }no funcionará.
Adry
1
@Miquel resuelto usando{query: 'var1='+foo+'&var2=bar'
Adry
32

Tengo un enfoque diferente: emito un evento justo después de conectarme, con los datos:

socket.on('connect',function(){ 
    // Send ehlo event right after connect:
    socket.emit('ehlo', data);
});

io.on('connection', function(client){
    // Receive ehlo event with data:
    client.on('ehlo', function(data) {
    });
});

Puede mantener una variable / objeto y decir, cuando no hay ningún ehloevento con datos, los otros eventos se ignoran hasta que ehlose envía.

Si esto no satisface, puede enviar datos directamente al conectarse, no copiaré el código, pero está en esta respuesta: https://stackoverflow.com/a/13940399/1948292

Daniel W.
fuente
6
Este es un buen enfoque para pasar datos para identificar a un usuario, como un token de acceso. Es posible que también desee controlar socket.on('reconnect', …)si su servidor necesita datos que podrían dejar de persistir después de una desconexión.
Iain Collins
15

Los connectioneventos se activan tan pronto como se establece la conexión TCP. No hay forma de enviar nada intermedio.

Lo que puede hacer es simplemente tomar el primer mensaje enviado por el servidor y poner los datos en ese mensaje. Sugiero encarecidamente implementar un protocolo delgado para esto, de modo que tenga varios tipos de mensajes y los use para determinar cómo el código debe procesar los datos.

Esto también sería más ampliable, ya que es bastante fácil crear una arquitectura genérica para eso. Si desea esperar a userdataque llegue primero, simplemente puede agregar algún estado a sus conexiones.

Ivo Wetzel
fuente
Hola Ivo, muchas gracias por responderme. ¿Puede darme un poco más de detalle sobre cómo lograr lo que está diciendo? ¡Gracias de nuevo!
Dan
Básicamente, tengo una aplicación de chat en funcionamiento, donde puedes enviar mensajes a clientes específicos. El problema es que no tengo forma de hacer coincidir el sessionId con el nombre de usuario. Entonces, si tú y yo estuviéramos charlando, en lugar de decir "Dan" e "Ivo", mostraría la identificación del cliente.
Dan
¿Puede darme un poco más de información sobre su arquitectura / código? ¿De dónde provienen las identificaciones y de dónde provienen los nombres? ¿No puede la aplicación simplemente hacer una solicitud al servidor y pedir los nombres de usuario asociados con las ID?
Ivo Wetzel
El nombre de usuario vendría de una base de datos (es decir, después de que un usuario inicie sesión). Los identificadores provienen de client.sessionId. Para ser honesto, implementé mi solución basándome en una respuesta que dio a una pregunta similar. Agrego clientes a medida que ingresan (al conectarse) a una matriz y los elimino al desconectarlos. Le paso los identificadores del cliente al cliente en el mensaje y me conecto. Está funcionando muy bien, así que muchas gracias por esa otra publicación :) Entonces, ¿estás diciendo que debería hacer una llamada a la base de datos e intentar hacer coincidir el id de sesión con un campo en la base de datos?
Dan
@Dan: simplemente almacene su sesión de usuario en Redis y guarde la clave en una cookie en el navegador del usuario. Obtenga la cookie en socket connect y envíela de vuelta al servidor.
Shripad Krishna
8

este es mi código para enviar datos de consulta a nodejs y server.io server client

var socket = io.connect(window.location.origin,{query:'loggeduser=user1'});

io.sockets.on('connection', function (socket) {
    var endp = socket.manager.handshaken[socket.id].address;
    console.log("query... " +  socket.manager.handshaken[socket.id].query.user);
});

consulta ... usuario1

mukut
fuente
2

este es mi código en la versión 2.1.1 del socket

//client side
var socket = io.connect(window.location.origin,{query:'loggeduser=user1'});

// server side
io.socket.on('connection', function (socket) {
    console.log("loggeduser => " +  socket.handshake.query.loggeduser);
});
Manoj Rana
fuente
0

Supongo que usará SSL.

El uso de cadenas de consulta para enviar datos confidenciales no es una buena práctica de seguridad ( ¿por qué? ). Creo que si necesita enviar datos no confidenciales, entonces la respuesta de Miquel es la más rápida y fácil, pero si lo que necesita enviar son datos confidenciales, entonces algo como Daniel W. es el mejor enfoque a tomar.

Para un enfoque de autenticación, puede echar un vistazo a este proyecto de github ( socketio-auth ) que, más allá del hecho de que actualmente no tiene mantenimiento, puede darle una buena idea de cómo lidiar con el problema.

oriuken
fuente