2012-01-31 10 views
12

Sto realizzando un semplice gioco online basato sul web. il gioco utilizza Socket.io per intercettarsi l'un l'altro. ma ho riscontrato il problema.Come posso gestire l'evento Close in Socket.io?

pensa alla seguente situazione. Ho eseguito il server Socket.io. un giocatore che fa la stanza, e un altro giocatore si unisce alla stanza. hanno giocato un po 'di tempo al gioco .. ma un giocatore è così arrabbiato e chiude la scheda del gioco.

in questa situazione, come posso ottenere l'evento su quale client è stato chiuso il browser sul lato server?

secondo i googling, popoli dicono così: "L'uso del browser-vicino evento come onbeforeunload"

ma so che tutti i browser non supportano eventi onbeforeunload. quindi voglio una soluzione su controllando l'evento di disconnessione del client in SERVER SIDE.

a Socket.io (nodeJS) console server-side, quando la connessione del cliente chiuso, la console dicono come segue:

di debug - scartando trasporto

La mia versione è nodeJS 0.4.10 e Socket.io la versione è 0.8.7. ed entrambi sono in esecuzione su Linux.

Chiunque può aiutare per favore?

codici shortend sono qui:

var io = require ("socket.io").listen (3335); 
io.sockets.on ("connection" , function (socket) 
{ 
    socket.on ("req_create_room" , function (roomId) 
    { 
    var socketInstance = io 
    .of ("/" + roomId) 
    .on ("connection" , function (sock) 
    { 
     sock.on ("disconnect" , function() 
     { 
      // i want this socket data always displayed... 
      // but first-connected-client doesn't fire this event .. 
      console.log (sock); 
     } 
    }); 
    }); 
}); 
+0

La mia risposta è stata utile? Ha risolto il tuo problema? –

risposta

7

C'è un evento disconnect che spara ogni volta che una connessione socket.io muore (si noti che è necessario questo, perché si può avere ancora una pagina wep aperta, ma cosa succede se la vostra connessione internet muore?). Prova questo:

var io = require('socket.io').listen(80); 

io.sockets.on('connection', function (socket) { 
    socket.on('disconnect', function() { 
    io.sockets.emit('user disconnected'); 
    }); 
}); 

sul tuo server. Tratto da Socket.IO website.

// EDIT

Così ho guardato il codice e ha fatto alcuni test a casa mia. Ho ottenuto gli stessi risultati di te e qui è la mia spiegazione. Stai cercando di rendere Socket.IO molto dinamico forzandolo dinamicamente ad ascoltare URL diversi (che vengono aggiunti in fase di runtime). Ma quando viene effettuata la prima connessione, in quel momento il server non ascolta l'altro URL. Sembra che esattamente a quel punto (quando la connessione è accettata) il gestore disconnect sia impostato per la prima connessione e non venga aggiornato in seguito (si noti che Socket.IO non crea nuove connessioni quando si chiama io.connect molte volte sul lato client) . Tutto sommato, questo sembra essere un bug! O forse c'è qualche spiegazione fantasiosa del perché questo comportamento dovrebbe essere così com'è, ma non lo so.

Lasciate che vi dica alcune altre cose. Prima di tutto questa creazione dinamica di ascoltatori non sembra essere un buon modo. Secondo me dovresti fare quanto segue: memorizzare le stanze esistenti e usare un url per tutte loro. Tenere l'ID di una stanza e quando si emette ad esempio l'evento message dal client, aggiungere l'ID di una stanza ai dati e gestirlo con un gestore message sul server. Penso che tu abbia l'idea. Spingi la parte dinamica nei dati, non negli url. Ma potrei sbagliarmi, almeno questa è la mia opinione.

Un'altra cosa è che il codice che hai scritto sembra essere cattivo. Notare che eseguire .on('connection', handler) molte volte lo farà sparare molte volte. Gli handler impilano l'uno sull'altro, non si sostituiscono l'un l'altro. Quindi questo è come vorrei implementare questa:

var io = require("socket.io").listen(app); 
var roomIds = []; 

function update_listeners(id) { 
    io.of("/"+id).on("connection", function(socket) { 
     console.log("I'm in room " + id); 
     socket.on("disconnect", function(s) { 
      console.log("Disconnected from " + roomId); 
     });    
    }); 
} 

var test = io.sockets.on("connection", function(socket) { 
    console.log("I'm in global connection handler"); 
    socket.on("req_create_room", function(data) { 
     if (roomIds.indexOf(data.roomId) == -1) { 
      roomIds.push(data.roomId); 
      update_listeners(data.roomId);  
     } 
     test.emit("room_created", {ok:true}); 
    }); 
    socket.on("disconnect", function(s) { 
     console.log("Disconnected from global handler"); 
    }); 
}); 

Tenete a mente che il problema con la creazione di collegamenti prima gli ascoltatori sono definiti sarà ancora occure.

+0

Grazie !! Funziona. ma ho ancora qualche problema qui ... su "disconnect" l'evento si attiva bene ma ad eccezione del primo client connesso. Voglio sapere perché il primo client connesso non può attivare l'evento "disconnect"? –

+0

Non so. Pubblica un po 'di codice e vedremo. – freakish

+0

Ho pubblicato il codice. questa è la versione ebrida .. grazie per il tuo aiuto –

17

Aggiornamento: Ho creato a blog post per questa soluzione. Qualsiasi commento è benvenuto!

Si consiglia di utilizzare l'opzione 'Sincronizza scollegamento in scaricamento' per Socket IO. Stavo avendo problemi simili, e questo mi ha davvero aiutato.

Sul client:

var socket = io.connect(<your_url>, { 
'sync disconnect on unload': true }); 

Non c'è bisogno di filo in qualsiasi scarico o beforeunload eventi. Ho provato questo in diversi browser, e ha funzionato perfettamente finora.

+1

Lei ha reso la mia giornata. Ho sprecato 7 ore cercando di trovare una soluzione a questo problema! –

+0

Link al post al posto del blog per favore – laggingreflex

+0

Ho aggiornato l'URL del link. –