websocket client close failed when switch network/ offline

1k Views Asked by At

i'd like to ask some question about how to close a websocket client when offline/switched network.

when i try to close the socket for the 2 case in chrome, after i call websocket.close, i cannot recieve onclose event for a long time (around 60s), then i can recieve it finally.

after i check the readystate, i found that in the coming 60s, the state is 2(CLOSEING), not turned to 3(CLOSED).

so i'd like to know is there any steps i missed when i call websocket.close() in offline/switched network condition. while it runs well when the network is normal.

1

There are 1 best solutions below

0
On

what's your back-end framework?

If you try to handle client's network that suddenly turned offline, there're two way you can try to close websocket from client as follows.

Kindly refer to source code here.

  1. Using the js offline event handle

    If we would like to detect if the user went offline we simply add websocket close function into offline event function.

    front-end

        function closeWebSocket() {
            websocket.close();
        }
    
        $(window).on('beforeunload offline', event => {
            closeWebSocket();
        });
    

    back-end (WebSocketServer)

        @OnClose
        public void onClose(Session session) {
            CURRENT_CLIENTS.remove(session.getId());
        }
    
  2. Using Ping interval on the client-side and decrease the websocket timeout on server-side

    If websocket server doesn't receive any message in specific time, it will lead to a timeout. So we can use this mechanism to decrease the timeout to close session if the client doesn't send any ping due to offline.

    front-end

        // send ping to server every 3 seconds
        const keepAlive = function (timeout = 20000) {
            if (websocket.readyState === websocket.OPEN) {
                websocket.send('ping');
            }
    
            setTimeout(keepAlive, timeout);
        };
    

    back-end (WebSocketConfig)

        @Bean
        public ServletServerContainerFactoryBean createWebSocketContainer() {
            ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
            container.setMaxSessionIdleTimeout(5000L);
    
            return container;
        }