How can i handle Close event in Socket.io?

2019-01-22 04:03发布

I'm making simple online game which based on Web. the game uses Socket.io for netwoking each other. but I encountered the problem.

think about following situation . I ran Socket.io server. one player making the room , and other player join the room. they played game some time .. but one player so angry and close the game tab.

in this situation , how can I get the event which one client have been closed the browser in server-side ?

according to googling , peoples say like this : "use browser-close event like onBeforeUnload"

but I know that All browser don't support onBeforeUnload event. so i want solution about checking the client disconnection event in SERVER SIDE.

in Socket.io ( nodeJS ) server-side console , when client's connection closed , the console say like following :

debug - discarding transport

My nodeJS version is 0.4.10 and Socket.io version is 0.8.7. and both are running on Linux.

Anyone can help please ?

shortend codes are here :

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

2条回答
Juvenile、少年°
2楼-- · 2019-01-22 04:46

Update: I created a blog post for this solution. Any feedback is welcome!

I recommend using the 'sync disconnect on unload' option for Socket IO. I was having similar problems, and this really helped me out.

On the client:

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

No need to wire in any unload or beforeunload events. Tried this out in several browsers, and its worked perfectly so far.

查看更多
兄弟一词,经得起流年.
3楼-- · 2019-01-22 05:02

There's an event disconnect which fires whenever a socket.io connection dies (note that you need this, because you may still have a wep page open, but what if your internet connection dies?). Try this:

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

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

at your server. Taken from Socket.IO website.

//EDIT

So I looked at your code and did some tests at my place. I obtained the very same results as you and here's my explanation. You are trying to make Socket.IO very dynamic by dynamically forcing it to listen to different urls (which are added at runtime). But when the first connection is made, at that moment the server does not listen to the other url. It seems that exactly at that point (when connection is accepted) the disconnect handler is set for the first connection and it is not updated later (note that Socket.IO does not create new connections when you call io.connect many times at the client side). All in all this seems to be a bug! Or perhaps there is some fancy explanation why this behaviour should be as it is but I do not know it.

Let me tell you some other things. First of all this dynamical creation of listeners does not seem to be a good way. In my opinion you should do the following: store the existing rooms and use one url for all of them. Hold the ID of a room and when you emit for example message event from client add the ID of a room to the data and handle this with one message handler at the server. I think you get the idea. Push the dynamic part into the data, not urls. But I might be wrong, at least that's my opinion.

Another thing is that the code you wrote seems to be bad. Note that running .on('connection', handler) many times will make it fire many times. Handlers stack one onto another, they do not replace each other. So this is how I would implement this:

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

Keep in mind that the problem with creating connections before the listeners are defined will still occure.

查看更多
登录 后发表回答