【问题标题】:Socket.io not firing events properly after disconnecting断开连接后 Socket.io 未正确触发事件
【发布时间】:2014-04-03 01:43:23
【问题描述】:

所以我想用 socket.io 构建一个小游戏应用程序,它的工作原理是这样的:

用户加载一个网站,我使用 generalConnection 命名空间创建一个通用套接字

app.generalSocket = io.connect('http://localhost/generalConnection');

我还没有关于它的任何特殊事件,但我认为将它与第二个命名空间分开会很好。

当用户登录时,我调用一个函数来启动游戏连接(另一个命名空间)并绑定一些事件,我不会一一列举,我认为这并不重要。

app.startGameSocket = function() {
    app.gameSocket = io.connect('http://localhost/gameConnection'); //game connection

    app.gameSocket.on("connect", function() {
        console.log("connected to the game socket");
    });
}

在服务器端我有类似的东西:

var connectedPlayers = [];
var gameConnection = io.of('/gameConnection').on('connection', function (socket) {
    socket.on('disconnect', function () {
        //some stuff
    });
});

再一次,我认为我不需要列出所有事件,我将解释它是如何工作的。

它监听新玩家事件,创建新玩家,将其推送到 connectedPlayers 数组,然后将其发送给连接到 gameConnection 命名空间的每个人。

用户列表已更新,大家都很高兴。当用户关闭浏览器窗口时,我还可以监听其他事件,例如断开连接并适当地更新 connectedPlayers 数组。

当用户从游戏中注销时,我还必须断开 gameConnection 命名空间,所以在客户端我这样做:

app.vent.on('logOut', function() {
    app.gameSocket.disconnect();
)};

请注意,我保持 generalConnection 命名空间打开,我只是断开了 gameConnection 命名空间。

效果很好,如果用户注销或关闭窗口,在服务器端触发断开事件,connectedPlayers 数组被更新并发送回连接的玩家。

问题

当用户:

  1. 进入网站。
  2. 登录游戏。
  3. 退出。
  4. 不刷新窗口再次登录(再次触发app.startGameSocket函数)。
  5. 在关闭窗口之后,游戏连接命名空间断开事件不会在服务器上触发,列表也不会更新。

Node shell 表示类似:info - 传输端(套接字端)但不触发断开连接事件。请帮忙:)

我试过

app.vent.on('logOut', function() {
    app.gameSocket.emit('forceDisconnect'); //force disconnect on the server side
    app.gameSocket.disconnect();
    app.gameSocket.removeAllListeners(); //tried to really kill disconnected socket
)};

但没有结果。

【问题讨论】:

  • 刚刚发现可以通过绑定app.gameSocket.disconnect();到 window.onbeforeunload 事件。所以当窗口关闭时连接被终止,但我很想了解什么是错的

标签: javascript node.js sockets websocket socket.io


【解决方案1】:

您可以配置 socket.io 以在窗口卸载时断开连接。

请参阅Socket.io wiki 中客户端的sync disconnect on unload 选项。此选项默认为 false,因此如果启用它应该可以解决您的问题。

app.gameSocket = io.connect('http://localhost/gameConnection', {'sync disconnect on unload':true}); //game connection

【讨论】:

  • 我用 window.onbeforeunload 做了类似的事情,但我或你的解决方案都没有完全修复它。如果您想了解更多信息,我已经详细回答了我的问题。
【解决方案2】:

Socket.io 没那么好玩!

在我的应用程序中,每次注销 > 登录过程是

app.gameSocket = io.connect('http://localhost/gameConnection'); //game connection

因此多次调用它会导致问题。我把它改成了这样:

app.firstConnect = true;

app.startGameSocket = function(){
    if(app.firstConnect){
        app.gameSocket = io.connect('http://localhost/gameConnection'); //game connection
    }else{
        app.gameSocket.socket.reconnect();
    }
}

app.vent.on('logOut', function(){
    app.firstConnect = false;
});

我的问题已经解决了,但是 socket.reconnect 引入了另一个问题!你可以在这里阅读它https://github.com/LearnBoost/socket.io/issues/430

【讨论】:

    【解决方案3】:

    socket如何识别连接到它的各种客户端,通过socket参数连接。然后所有其他事件被分配给 io.connection 块下的每个套接字客户端 作为 socket.on。每当任何客户端连接或断开连接时它自己的套接字事件(socket.on)被调用并且socket.io用那个套接字参数识别它并且每个套接字的 id。

    示例

    io.sockets.on('connection', function(socket //unique client socket as parameter) {
     //code block
    }
    

    例如:

    io.sockets.on('connection', function(socket) {
        //connect Me(socket)
        socket.on('connect', function() {
            console.log('disconnected')
        })
        //disconnect Me(socket)
        socket.on('disconnect', function() {
            console.log('disconnected')
        })
    });
    

    你的代码在做什么

    app.vent.on('logOut', function() {
        app.gameSocket.emit('forceDisconnect'); //force disconnect on the server side
        app.gameSocket.disconnect();
        app.gameSocket.removeAllListeners(); //tried to really kill disconnected socket
    )};
    

    它没有发出客户端特定socket

    的断开连接事件
    app.gameSocket.emit('forceDisconnect'); //force disconnect on the server side
    

    强制断开但断开谁?

    你需要这样的东西

    app.startGameSocket = function() {
        app.gameSocket = io.connect('http://localhost/gameConnection'); //game connection
    
        app.gameSocket.on("connect", function() {
            console.log("connected to the game socket");
        });
    
        //disconnect
        app.gameSocket.on("disconnect", function() {
            console.log("disconnected");
            //force disconnect/logout code
        });
    
        app.gameSocket.on('logOut', function() {
            //force disconnect/logout code
            app.gameSocket.emit('forceDisconnect'); //force disconnect on the server side
            app.gameSocket.disconnect();
            app.gameSocket.removeAllListeners(); //tried to really kill disconnected socket
        )};
    
    }
    

    【讨论】:

      猜你喜欢
      • 2016-09-20
      • 2018-01-28
      • 2011-11-03
      • 2014-01-08
      • 2019-05-01
      • 2020-09-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多