如何在socket.io中检测断开连接?

25
我在项目中使用了socket.io,并开启了重新连接功能。我想如果用户从服务器断开连接,就显示一个警告(你的互联网连接已断开。正尝试重连)。如果用户再次连接,我想显示另一个警告(别担心,你已连接)。
您如何实现这一功能?

请点击此处查看:https://stackoverflow.com/a/35124953/3904109 - DragonFire
4个回答

38

要在客户端检测,您可以使用

  // CLIENT CODE
  socket.on('disconnect', function(){
      // Do stuff (probably some jQuery)
  });

对于node.js服务器来说,这段代码与上述代码完全相同。

如果您希望由某种原因检测用户断开连接并将其显示给其他用户,则需要使用服务器端代码来检测该用户的离开情况,然后使用类似以下内容的内容向其他用户发出消息:

socket.on('disconnect', function(){
    socket.broadcast.to(roomName).emit('user_leave', {user_name: "johnjoe123"});
});
希望这可以帮助您。

谢谢您的回复。现在断开连接部分可以了,但是如何重新连接呢? - user2997295
1
服务器如何知道是干净断开还是客户端的互联网连接中断? - Mathew Kurian
@bluejamesbond 如果是干净的断开连接,你可以从客户端发出自定义的断开连接事件,在服务器上捕获它并通知其他人。 - Eric
为什么需要广播?我尝试过没有它,但失败了,你能帮我想出来吗? - Tu Le Anh

15

socket.io 有一个 disconnect 事件,请将其放在您的 connect 块中:

socket.on('disconnect', function () {
    //do stuff
});

1
请注意,如果客户端自己与服务器失去连接,事件disconnect直到套接字重试超时后才会触发。 - mobby
请注意,客户端方面,请不要将此代码放在connect回调函数中。该回调函数会在重新连接时触发,并逐渐注册更多的断开处理程序。 - Carcigenicate

4
我是一名有用的助手,可以为您进行翻译。
我处理这个问题的方式是:在客户端上创建了一个发射器,调用服务器上的心跳。
socket.on('heartbeat', function() {
        // console.log('heartbeat called!');
        hbeat[socket.id] = Date.now();
        setTimeout(function() {
            var now = Date.now();
            if (now - hbeat[socket.id] > 5000) {
                console.log('this socket id will be closed ' + socket.id);
                if (addedUser) {
                    --onlineUsers;
                    removeFromLobby(socket.id);

                    try {
                        // this is the most important part
                        io.sockets.connected[socket.id].disconnect();
                    } catch (error) {
                        console.log(error)
                    }
                }
            }
            now = null;
        }, 6000);
    });

我找到了这个调用函数的代码功能:
io.sockets.connected[socket.id].disconnect();

0

受到 invicibleTrain 的启发,我也做了一个在线检查器。

服务器端

const sockets={online:{},admins:{}}

// the disconnect function you create the way you wish to, example:
const disconnect=()=>{
  socket.emit('disconected')
  io.in(socket.id).disconnectSockets()
  delete sockets.online[socket.uid]
}

io.on('connection',socket=>{
  socket.emit('connection',socket.id)

  // the checker if user is online
  let drop
  const dropCheck=()=>{
    if(!socket) return; // if user connects twice before the check, simply stops process
    socket.emit('dropCheck')
    drop = setTimeout(()=>disconnect(),4000) // 4 secs to recieve answer
  }

  const setDrop=()=>setTimeout(()=>dropCheck(),60000) // 60 secs to restart the process

  socket.on('dropCheck',()=>{
    clearTimeout(drop) // cancells actual drop coutdown (if any)
    setDrop() // sets a new
  })

  //sets the user ID inside the socket used for comunication
  socket.on('uid',uid=>{
    socket.online[uid] = {status:'busy',socket:socket.id}
    setDrop()
  })
})

客户端

const sio = io(`...httpAddress...`,{transports:['websocket']})
sio.on('connection',socket=>{
  sio.emit('uid','user Id here..') // sends the the user ID: uid

  sio.on('dropCheck',()=>{ // responds to the checker
    sio.emit('dropCheck')
  })
})

说明:

  1. 用户登录后,60秒后调用dropCheck函数
  2. dropCheck函数发出ping信号并设置4秒的计时器
  3. 用户处理发出的ping信号并回复另一个ping信号
  4. a:如果响应在4秒内到达,则取消4秒计时器并刷新60秒计时器(重新开始过程)
  5. b:如果响应失败或延迟太长,则调用disconnect()函数

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接