Foros del Web » Programando para Internet » Node.js »

[SOLUCIONADO] Cierre de sección automatico

Estas en el tema de Cierre de sección automatico en el foro de Node.js en Foros del Web. Buenas comunidad, hoy le traigo un problemita de sessiones abiertas a ver si alguno me podeis echar un cable. Tengo montado un sistema de usuarios, ...
  #1 (permalink)  
Antiguo 06/09/2013, 09:19
 
Fecha de Ingreso: junio-2009
Mensajes: 128
Antigüedad: 15 años, 5 meses
Puntos: 17
Cierre de sección automatico

Buenas comunidad, hoy le traigo un problemita de sessiones abiertas a ver si alguno me podeis echar un cable.

Tengo montado un sistema de usuarios, con su login tipico, validaciones y to la pesca, me apoyo en el uso de sockets, para gestionar las conexiones en tiempo real (cuando un usuario se desconecta o se conecta, se envia notificaciones al resto de usuarios en activos).

Hasta aqui todo genial y sin problemas, Cuando logeo, se informa al resto, cuando deslogeo se informa tambien. Pero hay una tercera variante que es la que me esta rompiendo totalmente la funcionabilidad del sistema y es cuando el usuario cierra la ventana del navegador y se pira, si haber pulsado en el boton de "offlogin", por lo tanto nunca se ejecuta mi script de desconexión, no se actualiza su estado en la bbdd y no se envia por socket al resto de usuarios su desconexión, quedando permanentemente on.

Como podemos observar esta es una cagada considerable en el sistema. He leido bastante sobre los eventos de javascript para lanzar un evento al momento de cerrar el navegador. Pero esta solución es incompleta, Opera no trabaja este evento, la mayoria de navegadores moviles tampoco, y tenemos la siempre presente posibilidad de desconexión por fallo en la red, se fue la covertura movil, por que se fue la luz y el pc se apago de golpe (o el movil/tablet se quedo sin pilas).

¿Alguien conoce la forma de hacer que el propio servidor detecte cuando un cliente deja de responder en el socket y automaticamente lanzara mi script de desconexión?

Seguramente no sea algo dificil (espero), pero caminar por senderos nuevos siempre nos provoca hacer preguntas tontas hasta que aprendemos las respuestas :D

Espero que puedan ayudarme.
Un saludo a la comunidad.
  #2 (permalink)  
Antiguo 07/09/2013, 07:24
Avatar de nemesis866  
Fecha de Ingreso: julio-2009
Ubicación: Jalisco, Mexico
Mensajes: 643
Antigüedad: 15 años, 4 meses
Puntos: 20
Respuesta: Cierre de sección automatico

Que tal Kikeking1, en mi caso yo uso disconnect, con esto detecto cuando un socket (en este caso un usuario) se desconecta de la aplicacion y ejecuto el codigo necesario para informar lo sucedido.

Código Javascript:
Ver original
  1. io.sockets.on("connection", inicio);
  2.  
  3. function inicio (socket){
  4.     socket.on("disconnect", desconectado);
  5. }
  6. function desconectado(){
  7.         aqui me va el codigo que se ejecuta cuando se desconecta un usuario...
  8. }

Saludos y espero te sirva
__________________
Artículos de programación Web
Twitter.- @codeandoclub
  #3 (permalink)  
Antiguo 08/09/2013, 21:08
Avatar de utan  
Fecha de Ingreso: agosto-2012
Mensajes: 126
Antigüedad: 12 años, 3 meses
Puntos: 17
Respuesta: Cierre de sección automatico

Que estas usando para conectarte?

Es con raw socket oh algun Api como socket.io , si es con socket.io la respuesta anterior es correcta pues socket.io detecta si el socket se desconecto por medio

timeout creo que por defecto es 25 segundos, manda un evento al client si el cliente responde lo mantiene vivo, ahora también el socket.io cliente detecta el onunload event del browser desconectando al cliente..

Si no estas usando socket.io , y es puro raw socket podrias usar tambien el onunload evento pero no todos los browsers lo soportan sin embargo si estas usando raw socket ya estas usando un browser lo suficientemente al dia.. y el onunload deberia de ayudarte.

ejemplo

Código PHP:

    
var socket = new WebSocket('ws://game.example.com:12010/updates');
    
socket.onopen = function () {
        
console.log('connectedados');
    };
    
// mandas que se esta desconectando
    
window.onunload=function(){
        
socket.send('disconnecting' , { whom id});
    } 
Ese es un ejemplo claro, pero la idea va por ayi.
__________________
Mis conocimientos son limitado, pero si te puedo ayudar lo are gustoso mi chat particular, visitalo gracias http://rendezvouschat.com
  #4 (permalink)  
Antiguo 12/09/2013, 06:28
 
Fecha de Ingreso: junio-2009
Mensajes: 128
Antigüedad: 15 años, 5 meses
Puntos: 17
De acuerdo Respuesta: Cierre de sección automatico

Lo primero de todo, agraderos vuestra respuestas y disculparme por mi tardanza en responder, vi vuestros comentarios hace unos días, pero no queria responder hasta tener algo solido que decir.

Efectivamente la solución se encontraba en usar los eventos de "connection" y "disconnect", el mayor problema que esto me ocasionaba era cuando resfrecaba página o cambiaba de sección. Cada vez que esto se produce, el socket se destruia provocando que se disparara el evento de "disconnect" lo cual no me servia.

La solución que he seguido es apoyandome en el apreton de mano (handshake). Como uso sessiones basadas en cookie, solo debía comprobar la id de session en la cookie del cliente al momento que los socket que se crean y compararla con el store de session en el servidor... Así dicho suena fácil y una vez terminado...realmente lo es, pero para ser la primera vez, ha sido una odisea considerable que me llevo 3 días solventar (a la próxima seguro que es menos ).

Dejo el codigo de configuración del "authorization" del socket y del "connection", para que a aquellos en mi situación que llegen hasta este hilo puedan ahorrar el tiempo que yo gaste.

Si teneis alguna duda sobre el codigo, preguntar sin miedo e intento ayudaros en lo que pueda.

Código Javascript:
Ver original
  1. app.io.set('authorization', function (handshake_data, accept) {
  2.         var data = handshake_data;
  3.         if (data.headers.cookie) {
  4.             data.cookie = parseCookie(data.headers.cookie,SECRET);
  5.             data.sessionID = data.cookie.signedCookies[KEY]||data.cookie.cookies[KEY];
  6.             store.load(data.sessionID, function (err, session) {
  7.                 if (err) {
  8.                     console.log('error');
  9.                     accept(err.message, false);
  10.                 }
  11.                 else if (session==undefined) {
  12.                     console.log('sesión no encontrada en servidor, Id de sesión entrante: '+data.sessionID )
  13.                     accept('sesión no encontrada', false);
  14.                 }
  15.                 else {
  16.                     data.session = session;
  17.                     if(!data.session.userid){
  18.                         data.session.userid=require('express/node_modules/connect/lib/utils').uid(24);
  19.                         data.session.save(function(){ })
  20.                     }
  21.                     accept(null, true);
  22.                 }
  23.             });
  24.         } else {
  25.             if (data.query.secret_keyword && (data.query.secret_keyword === app.io.secret_keyword)) {
  26.                 return accept(null, true);
  27.             }
  28.             return accept('Cookie no tramitada.', false);
  29.         }
  30.     });

Código Javascript:
Ver original
  1. var timeoutID = [];
  2. GLOBAL.connect_sockets = []
  3. app.io.sockets.on('connection', function (socket) {
  4.     var hs = socket.handshake;
  5.     var user = hs.session['usid'];
  6.     if(!timeoutID['u'+user]){ timeoutID['u'+user] = [];}
  7.  
  8.     console.log('El usuario con id '+hs.session['usid']+' y nombre '+hs.session['nick']+' ha abierto la session '+hs.sessionID);
  9.     connect_sockets["id"+hs.session['usid']]=socket.id;
  10.    
  11.     if (timeoutID['u'+user] && timeoutID['u'+user].length > 0){
  12.         for (var i in timeoutID['u'+user]) {
  13.             if(timeoutID['u'+user][i]._idleTimeout){
  14.                 clearTimeout(timeoutID['u'+user][i]);
  15.                 delete timeoutID['u'+user][i];
  16.             }
  17.         }
  18.     }
  19.  
  20.     socket.on('disconnect', function () {
  21.         timeoutID['u'+user].push(setTimeout(function () {
  22.             if(hs.session.login){
  23.                 client.query("ACTUALIZO EL ESTADO EN LA BBDD idUsuario='"+hs.session['usid']+"' LIMIT 1", function selectCb(err, results, fields) {
  24.                         if(err){console.log('Error offlogin'); }
  25.                         else{
  26.                             if(!hs.session.ninja||hs.session.ninja=='no'){
  27.                                 app.io.broadcast('GLOBAL-login', {ninja:false,id:hs.session['usid']}); //ninja es login
  28.                             }
  29.                             console.error('El usuario con id '+hs.session['usid']+' y nombre '+hs.session['nick']+' ha cerrado la sesion '+hs.sessionID);
  30.                             hs.session.destroy();
  31.                         }
  32.                 });
  33.             }
  34.         }, 10 * 1000) );
  35.     });
  36.    
  37. });


Para el desarrollo de este codigo me base en la autentificación de este chat: https://gist.github.com/shimondoodkin/4072034

Espero que todo esto sirva de ayuda a alguien en el futuro, tal y como me ha servido a mi. Nuevamente Gracias a Nemesis866 y Utan por su tiempo y ayuda.

Un saludo comunidad.

P.D.: Ciertamente se me olvido decir la tecnologia que estaba usando, siendo lo primero que deberia haber dicho ¬¬. En fin, estoy usando express.io (que es el framework de express+socket.io ya integrado), uso cookie para el control de las sessiones y mysql para la bbdd.

EDIT: He actualizado el codigo, pues el anterior tenia unos fallos que corregi estos días, ahora trabaja fino.. it´s work!

Última edición por kikeking1; 19/09/2013 a las 08:50 Razón: He actualizado el codigo, pues el anterior tenia unos fallos que corregi estos días, ahora trabaja fino.. it´s work!

Etiquetas: automatico, cierre
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 08:04.