admin管理员组

文章数量:1410717

I am creating an online multiplayer game in JavaScript (JS), think Lichess or Chess but for another game. I now want to detect if a user disconnects but having trouble figuring out how to do this reliably. It doesn't matter if user closes the tab, the window, or loses internet connection. I need to know if any of the events happen. However, they should be allowed to switch tabs, windows or similar, as long as they don't close the game.

I use socket.io for websocket communication.

Problems and what I have tried

So far I have tried some different solutions:

  1. Handle it in sockets disconnect event: socket.on('disconnect', () => { console.log('User disconnected) }); But this is not reliable and doesn't always fire.

  2. Using a ping/pong system where client sends a signal to server to let it know it is alive. But if I switch tab or window it seems that JS starts throttling, or even stops completely.

    socket.on("connect", () => {     
        if (!heartbeatInterval) {
            heartbeatInterval = setInterval(() => {
                socket.emit("pong");
            }, 4000);
        }
    });
    
  3. To get around the problem in point 2 I tried using a Web Worker. The problem with that is that even if I closes a tab or window it keeps going. I tried stopping it in window.addEventListener("beforeunload", () => {... but it doesn't always fire, so basically opposit problem to point 2.

     heartbeatWorker = new Worker('/heartbeatWorker.js');
     heartbeatWorker.onmessage = () => {
         socket.emit("pong");
     };
     heartbeatWorker.postMessage('start');
    

Question

How can I create a reliable disconnect system similar to Lichess or Chess with above requirements?

I am creating an online multiplayer game in JavaScript (JS), think Lichess or Chess but for another game. I now want to detect if a user disconnects but having trouble figuring out how to do this reliably. It doesn't matter if user closes the tab, the window, or loses internet connection. I need to know if any of the events happen. However, they should be allowed to switch tabs, windows or similar, as long as they don't close the game.

I use socket.io for websocket communication.

Problems and what I have tried

So far I have tried some different solutions:

  1. Handle it in sockets disconnect event: socket.on('disconnect', () => { console.log('User disconnected) }); But this is not reliable and doesn't always fire.

  2. Using a ping/pong system where client sends a signal to server to let it know it is alive. But if I switch tab or window it seems that JS starts throttling, or even stops completely.

    socket.on("connect", () => {     
        if (!heartbeatInterval) {
            heartbeatInterval = setInterval(() => {
                socket.emit("pong");
            }, 4000);
        }
    });
    
  3. To get around the problem in point 2 I tried using a Web Worker. The problem with that is that even if I closes a tab or window it keeps going. I tried stopping it in window.addEventListener("beforeunload", () => {... but it doesn't always fire, so basically opposit problem to point 2.

     heartbeatWorker = new Worker('/heartbeatWorker.js');
     heartbeatWorker.onmessage = () => {
         socket.emit("pong");
     };
     heartbeatWorker.postMessage('start');
    

Question

How can I create a reliable disconnect system similar to Lichess or Chess with above requirements?

Share Improve this question asked Mar 5 at 19:02 eligolfeligolf 1,8861 gold badge9 silver badges32 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

It is true that the socket disconnect event does not always fire upon closing the tab. However, it seems that you can send off one message in the onbeforeunload handler. You don't need a WebWorker.

window.addEventListener("beforeunload", function(event) {
    socket.emit("closePage");
});

Then you can have a listener on the server for both the socket disconnect event and for the closePage event. From my experience, this closePage will always fire when the user closes the tab or window, or restarts their PC. The disconnect will usually fire right when they lose internet connection, or will fire after a timeout period. As long as the tab is open and the computer is on neither of these fires.

The situation on mobile is more complicated since mobile OSs like to suspend pages and connections when they aren't active. However, the closePage event still fires when the tab is closed. The browser usually completes a disconnect when it suspends a page, so the disconnect event will fire on the server

From an alternative approach, we focus exclusively on client-side logic: if a user fails to connect to the server for any reason within a defined period, they are considered offline. For game sessions, the server maintains real-time game state persistence during a match. Upon reconnection, the client synchronizes with the server-stored game state to resume gameplay.

本文标签: socketioHandle disconnects in multiplayer JavaScript gameStack Overflow