Socket.io'断开事件'重新连接后发射太晚了

时间:2017-08-19 14:22:21

标签: node.js sockets socket.io

我在我的sql数据库中为用户设置了离线的简单代码。

服务器

io.on('connection', function (socket) {
   ApiHelper.setUserOnline(socket.token);

   socket.on('disconnect', function () {
      ApiHelper.setUserOffline(socket.token);
   });
}

让我们说,

用户连接到套接字而不是丢失网络连接然后重新连接。

我收到了这些日志。

  • 用户已连接(他在线)
  • 网络丢失。
  • 网络已丢失但服务器尚未收到断开连接事件,因此用户仍在线
  • 用户重新连接到网络,然后再插入套接字。用户仍然在线。
  • 服务器和用户接收的先前断开连接事件在数据库中设置为脱机。 但等待用户刚刚重新连接,所以实际上用户必须在线。

由于已触发断开连接事件,我们发现用户在数据库中处于脱机状态。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

我认为最好的方法是将socket.id存储在sql数据库中,所以当用户登录/连接时,首先要检查user.account是否已经在线。

如果它在线,那么使用旧的socket.id来通知该帐户已从另一个窗口/设备/任何内容打开,并将其替换为db中的新socket.id

并且通过将新的socket.id替换为db中的新socket.id,当发生断开连接时,您将真正知道它是否是使用该帐户的当前活动客户端(socket.id)。

所以在disconnection:检查断开连接 socket.id是否在数据库中     (换句话说:目前是否连接)

io.on('connection', function (socket) {
   /* check if the account associated to this socket was
      previously associated to another socket.id ...
     (that might be currently connected or about to disconnect (lost connection)
   */
   if(thisAccountWasOnlineBefore){
    socket.to(old.socket.id).emit('exit', 'account opened from another session');
   }
   //pass also the socket.id so you can store it in the db
   ApiHelper.setUserOnline(socket.id, socket.token);

   socket.on('disconnect', function () {
      //check if socket.id is associated to any account in the db
      // if true : remove the socket.id and set as account status : offline
   });
}