【问题标题】:Socket.io 'disconnect event' firing too late after reconnect重新连接后,Socket.io“断开连接事件”触发太晚
【发布时间】:2018-01-28 02:02:23
【问题描述】:

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

服务器

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

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

可以这么说,

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

我得到了这个日志。

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

由于断开连接事件触发较晚,我们看到用户在数据库中处于离线状态。

我怎样才能解决这个问题?

【问题讨论】:

  • 每个会话是否有唯一的 ID 或类似的东西?
  • @tobifasc 是的,令牌是每个用户的唯一 ID。
  • 我的意思不是针对每个用户,而是针对用户创建的每个会话。您可以将会话 ID 添加到已连接和已断开连接的日志中。因此,当用户使用旧会话 ID 断开连接但他已经获得了新会话 ID 时,他不会与新会话 ID 断开连接。你明白了吗?
  • 如果用户打开了多个选项卡,此代码将永远无法工作。我建议维护给定用户拥有多少连接的计数,并且仅在计数变为零时才设置为脱机。然后,您不必关心事件的顺序,如果用户碰巧在您的网站上使用多个选项卡或计算机,您的代码将正常工作。
  • @jfriend00,我得到了它并编写了它运行良好的代码。

标签: node.js sockets socket.io


【解决方案1】:

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

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

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

所以在 disconnection :检查 disconnecting 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
   });
}

【讨论】:

  • 每次用户连接时都会得到一个新的、唯一的socket.id,因此将其存储在数据库中是没有意义的:1.连接时socket.id不在数据库中,2当它断开连接时,它的 socket.id 肯定在数据库中
  • @mk12ok 你所说的毫无意义,当然它是新的和独特的,但这样你就会知道当前使用哪个帐户的 id,所以当发生断开连接时,你可以检查它是否对应连接到活动用户的套接字连接或旧用户的连接(防止断开当前活动的连接)。
  • 这对于您一次只能从一个实例访问帐户的游戏特别有用。 (因此,当您使用已打开的同一个帐户连接时,旧客户端会收到一条消息“连接丢失:此帐户是从另一个客户端打开的。”):)
猜你喜欢
  • 2016-03-28
  • 2014-01-08
  • 2016-09-20
  • 2014-04-03
  • 2011-11-03
  • 2019-05-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-21
相关资源
最近更新 更多