我如何在Socket.io中处理Close事件?

Jin*_*ung 12 node.js socket.io

我正在制作基于Web的简单在线游戏.游戏使用Socket.io互相进行网络互动.但我遇到了这个问题.

想想以下情况.我运行了Socket.io服务器.一个玩家制作房间,其他玩家加入房间.他们玩游戏一段时间..但是一个玩家如此愤怒并关闭游戏标签.

在这种情况下,如何在服务器端获取一个客户端关闭浏览器的事件?

根据谷歌搜索,人们这样说:"使用浏览器关闭事件,如onBeforeUnload"

但我知道所有浏览器都不支持onBeforeUnload事件.所以我想要在SERVER SIDE中检查客户端断开连接事件的解决方案.

在Socket.io(nodeJS)服务器端控制台中,当客户端的连接关闭时,控制台说如下:

调试 - 丢弃传输

我的nodeJS版本是0.4.10,Socket.io版本是0.8.7.两者都在Linux上运行.

有人可以帮忙吗?

短代码在这里:

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 );
       }
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

小智 18

更新:我为此解决方案创建了一篇博文.欢迎任何反馈!

我建议使用Socket IO的'sync disconnect on unload'选项.我遇到了类似的问题,这真的帮助了我.

在客户端:

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

无需在任何卸载事先卸载事件中进行连接.在几个浏览器中尝试了这一点,到目前为止它的工作完美.

  • 你先生让我开心。我已经浪费了 7 个小时试图找到解决此问题的方法! (2认同)

fre*_*ish 8

有一个事件disconnect会在socket.io连接断开时触发(注意你需要这个,因为你可能仍然打开一个wep页面,但是如果你的互联网连接死了怎么办?).试试这个:

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

io.sockets.on('connection', function (socket) {
  socket.on('disconnect', function () {
    io.sockets.emit('user disconnected');
  });
});
Run Code Online (Sandbox Code Playgroud)

在你的服务器上.取自Socket.IO网站.

//编辑

所以我看了你的代码并在我的地方做了一些测试.我得到了和你一样的结果,这是我的解释.您试图通过动态强制Socket.IO监听不同的URL(在运行时添加)来使Socket.IO非常动态.但是当第一次连接时,服务器在那时不会监听另一个URL.似乎恰好在那一点(当接受连接时)disconnect处理程序被设置为第一个连接并且它不会在以后更新(请注意,当您io.connect在客户端多次调用时,Socket.IO不会创建新连接).总而言之,这似乎是一个错误!或者也许有一些奇特的解释为什么这种行为应该是这样,但我不知道.

我告诉你一些其他的事情.首先,这种动态创造听众似乎并不是一个好方法.在我看来,你应该做以下事情:存储现有的房间,并为所有房间使用一个网址.保存房间的ID,当您message从客户端发出例如事件时,将房间的ID添加到数据中,并使用message服务器上的一个处理程序处理.我想你应该已经明白了.将动态部分推入数据,而不是网址.但我可能错了,至少这是我的看法.

另一件事是你写的代码似乎很糟糕.请注意,.on('connection', handler)多次运行会使其多次触发.处理程序将一个堆叠到另一个上,它们不会互相替换.这就是我实现这个的方法:

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");
    });
});
Run Code Online (Sandbox Code Playgroud)

请记住,在定义侦听器之前创建连接的问题仍将发生.