【问题标题】:Socket.io page refresh disconnects from the roomSocket.io 页面刷新与房间断开连接
【发布时间】:2017-03-21 17:54:45
【问题描述】:

一段时间以来,我一直在阅读有关此问题的答案,但似乎没有一个解决方案适用于我的设置。

我有一个 nodeJS 服务器与 express 结合使用。我使用 Socket.io 向个人用户发送通知。 (前端是 Angular)

当用户登录时,他会加入一个以他的电子邮件地址命名的房间(唯一)。

  io.on('connection', function (socket) {
    socket.on('join', function(user) {
      //list of connected users
      connected_users.push({socket_id: socket.id, email: user.email});
      socket.join(user.email);
    });
    ...

join 事件在用户登录时从角度广播。

这样我就可以简单地使用电子邮件地址发送通知:

io.sockets.in(to).emit('notification', {
  message: msg,
  source: from,
  destination: to,
  event: data
});

当用户手动注销时,我会注册以下事件监听器:

socket.on('leave', function(user) {
  //remove the user from the list
  var index = findUserConnected(socket.id);
  if(index != null) {
    connected_users.splice(index, 1);
  }
  socket.leave(user.email);
});

最后还有 disconnect 处理程序,用于每当用户注销或刷新页面时:

socket.on('disconnect', function() {
  //if the user refreshes the page, he is still in the connected users list
  var email = findEmailUserConnected(socket.id);
  if(email != null) {
    //we make him join back his room
    socket.join(email);
  }
});

从技术上讲,这是可行的。在页面刷新时,用户重新加入他的房间。

问题仅在于页面刷新时,即使用户在他的房间里,也不会收到使用io.sockets.in(email).emit('notification', {}); 发送的通知。

显然页面刷新调用socket.disconnect() 生成一个新的socket_id。我不确定是否有办法将 socket_id 重新分配给房间或类似的东西。

【问题讨论】:

  • 页面重新加载会破坏所有页面资源,包括 webSocket/socket.io 连接。再次加载页面会创建一个新连接。您可能需要使用 cookie 来创建某种持久的会话 id,以便您可以识别以前的用户并在服务器上恢复他们的状态。
  • @jfriend00 “在服务器上恢复他们的状态”是什么意思?当页面刷新时,我已经有了socket.join,用户被识别......等等。
  • connection 事件中,您需要能够识别您之前已配置到房间中的套接字并将其状态设置回您想要的方式(将其放回房间,更新属于该用户的socket.id,等等...通常,人们会使用从 cookie 中获得的信息,将这个新的传入连接与您之前见过的特定用户相关联。
  • 我明白,但我如何以及在哪里“更新 socket.id”?我可以设置房间的socketid吗?我确实有唯一的电子邮件地址和相应的 socketid 的记录。我已经重新加入了房间。我应该把那个socketid放在哪里?
  • 更新什么socket.id?没有房间的socket.id。一个房间有一个名字,里面有一个套接字列表。这就是一个房间。

标签: angularjs node.js express socket.io


【解决方案1】:

好的,首先在服务器上接收到“断开连接”事件意味着该套接字上的连接将终止。因此,像您现在所做的那样,将相同的套接字连接回房间是没有用的。

socket.on('disconnect', function() {
    var email = findEmailUserConnected(socket.id);
    if(email != null) {
        socket.join(email); // this would never work because this socket connection is not going to exist anymore.
    }
});

我的建议是确保每次建立新连接时用户总是重新加入房间(电子邮件)。通过在每个新连接上添加发送加入事件可以轻松完成。 在你的客户端代码中做

var socket = io();
socket.on('connect', function() {   //  'connect' event is received on client on every connection start.
    socket.emit('join', user);  //  where 'user' is your object containing email.
})

这样可以确保无论何时建立新连接,都会将加入事件发送到服务器,并且服务器中的 'socket.on('join',...)' 侦听器会将新套接字添加到房间。希望这会有所帮助:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-30
    • 1970-01-01
    • 1970-01-01
    • 2018-01-01
    • 2018-02-15
    • 2017-06-14
    • 1970-01-01
    • 2021-01-28
    相关资源
    最近更新 更多