Detailed explanation of JS WebSocket disconnection reasons and heartbeat mechanism

Detailed explanation of JS WebSocket disconnection reasons and heartbeat mechanism

1. Disconnection reason

There are many reasons why WebSocket is disconnected. It is best to print out the error when WebSocket is disconnected.

ws.onclose = function (e) {
  console.log('websocket disconnected: ' + e.code + ' ' + e.reason + ' ' + e.wasClean)
  console.log(e)
}

Error status code:

When a WebSocket is disconnected, a CloseEvent is triggered. CloseEvent is sent to the client using WebSockets when the connection is closed. It is used in the onclose event listener of the WebSocket object. The code field of CloseEvent indicates the reason why the WebSocket was disconnected. The reason for the disconnection can be analyzed from this field.

There are three fields in CloseEvent that need attention. By analyzing these three fields, we can generally find the reason for disconnection.

CloseEvent.code: code is the error code, which is an integer type

CloseEvent.reason: reason is the reason for disconnection, a string

CloseEvent.wasClean: wasClean indicates whether the disconnection was normal, which is a Boolean value. Generally, when an abnormal disconnection occurs, the value is false.

Status Code name describe
0–999 Reserved segment, not used.
1000 CLOSE_NORMAL Normal closure; whatever purpose the link was created for, the link has successfully completed its task.
1001 CLOSE_GOING_AWAY The terminal is leaving, either because of a server error or because the browser is leaving the page that opened the connection.
1002 CLOSE_PROTOCOL_ERROR The connection was aborted due to a protocol error.
1003 CLOSE_UNSUPPORTED The connection was terminated because an unacceptable data type was received (e.g., binary data was received on a terminal that only accepts text data).
1004 Reserved. Its meaning may be defined in the future.
1005 CLOSE_NO_STATUS Reserved. Indicates that the expected status code was not received.
1006 CLOSE_ABNORMAL Reserved. Used when a status code is expected and the connection was closed abnormally (that is, no Close frame was sent).
1007 Unsupported Data The connection was terminated due to receiving data that does not conform to the given format (e.g. a text message containing non-UTF-8 data).
1008 Policy Violation The connection was disconnected due to receiving data that does not conform to the protocol. This is a general status code used in situations where status codes 1003 and 1009 are not appropriate.
1009 CLOSE_TOO_LARGE The connection was terminated due to receiving a data frame that was too large.
1010 Missing Extension The client expected the server to negotiate one or more extensions, but the server did not handle them, so the client was disconnected.
1011 Internal Error The server disconnected because the client encountered an unexpected condition that prevented it from completing its request.
1012 Service Restart The server is disconnected due to reboot.
1013 Try Again Later The server disconnected due to temporary reasons, such as server overload, so some clients were disconnected.
1014 Reserved by the WebSocket standard for future use.
1015 TLS Handshake Keep. Indicates that the connection was closed because the TLS handshake could not be completed (e.g. the server certificate could not be verified).
1016–1999 Reserved by the WebSocket standard for future use.
2000–2999 Reserved for use by the WebSocket extension.
3000–3999 May be used by libraries or frameworks.? Should not be used by applications. May be registered with IANA on a first-come, first-served basis.
4000–4999 Can be used by applications.

2. Add heartbeat

var lockReconnect = false; //Avoid repeated ws connections var ws = null; //Determine whether the current browser supports WebSocket
var wsUrl = serverConfig.socketUrl;
createWebSocket(wsUrl); //Connect to ws

function createWebSocket(url) {
    try{
        if('WebSocket' in window){
            ws = new WebSocket(url);
        }
        initEventHandle();
    }catch(e){
        reconnect(url);
        console.log(e);
    }     
}

function initEventHandle() {
    ws.onclose = function () {
        reconnect(wsUrl);
        console.log("llws connection closed!"+new Date().toLocaleString());
    };
    ws.onerror = function () {
        reconnect(wsUrl);
        console.log("llws connection error!");
    };
    ws.onopen = function () {
        heartCheck.reset().start(); //Heartbeat detection reset console.log("llws connection successful!"+new Date().toLocaleString());
    };
    ws.onmessage = function (event) { //If a message is received, the heartbeat detection is reset heartCheck.reset().start(); //Getting any message means that the current connection is normal console.log("llws received the message:" + event.data);
        if(event.data!='pong'){
            let data = jsON.parse(event.data);
        }
    };
}
// Listen for window closing events. When the window is closed, actively close the websocket connection to prevent the server from throwing an exception when the window is closed before the connection is disconnected.
window.onbeforeunload = function() {
    ws.close();
}  

function reconnect(url) {
    if(lockReconnect) return;
    lockReconnect = true;
    setTimeout(function () { //If it fails to connect, it will keep reconnecting. Set a delay to avoid too many requests createWebSocket(url);
        lockReconnect = false;
    }, 2000);
}

//Heartbeat detection var heartCheck = {
    timeout: 1000, //Send a heartbeat every minute timeoutObj: null,
    serverTimeoutObj: null,
    reset: function(){
        clearTimeout(this.timeoutObj);
        clearTimeout(this.serverTimeoutObj);
        return this;
    },
    start: function(){
        var self = this;
        this.timeoutObj = setTimeout(function(){
            //Here a heartbeat is sent, and after the backend receives it, a heartbeat message is returned.
            //onmessage gets the returned heartbeat, which means the connection is normalws.send("ping");
            console.log("ping!")
            self.serverTimeoutObj = setTimeout(function(){//If it is not reset after a certain period of time, it means that the backend has actively disconnected ws.close(); //If onclose will execute reconnect, we just need to execute ws.close(). If reconnect is executed directly, onclose will be triggered, resulting in two reconnections}, self.timeout)
        }, this.timeout)
    }
}
    //Method called after receiving client message @OnMessage  
    public void onMessage(String message, Session session) {  
        if (message.equals("ping")) {
        }else{
        . . . .
        }
   }

The system found that the websocket automatically disconnected every 1 minute. I searched many blogs and they all said to set nginx's proxy_read_timeout, but this time is too long and will affect the server performance. The heartbeat packet method is used so that the client automatically sends a ping message to the server every 1 minute, and the server needs to return a pong. The problem can be solved.

The above is a detailed explanation of the reasons for JS WebSocket disconnection and the heartbeat mechanism. For more information about the reasons for JS WebSocket disconnection and the heartbeat mechanism, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • How to use JS WebSocket to implement simple chat
  • js realizes real-time transmission of mp3 recording via websocket + simple waveform effect
  • Native nodejs uses websocket code sharing
  • How to use websocket based on express in node.js
  • JS implements the effect of websocket long polling real-time message prompt
  • Improved version of nodejs+websocket real-time chat system
  • Websocket+node.js to implement real-time chat system problem consultation
  • Implementation of WebSocket communication based on Node.js
  • Node.js websocket uses socket.io library to implement real-time chat room
  • Javascript WebSocket usage examples (concise introductory tutorial)

<<:  How to install setup.py program in linux

>>:  How to deploy python crawler scripts on Linux and set up scheduled tasks

Recommend

MySQL data compression performance comparison details

Table of contents 1. Test environment 1.1 Hardwar...

Various problems encountered by novices when installing mysql into docker

Preface Recently, my computer often takes a long ...

Pure CSS to achieve candle melting (water droplets) sample code

Achieve results Implementation ideas The melting ...

Additional instructions for using getters and actions in Vuex

Preliminary Notes 1.Differences between Vue2.x an...

Solve the scroll-view line break problem of WeChat applet

Today, when I was writing a small program, I used...

CentOS6 upgrade glibc operation steps

Table of contents background Compile glibc 2.14 M...

MySQL trigger simple usage example

This article uses examples to illustrate the simp...

Example code for implementing ellipse trajectory rotation using CSS3

Recently, the following effects need to be achiev...

Understanding and solutions of 1px line in mobile development

Reasons why the 1px line becomes thicker When wor...

Example code for implementing bottom alignment in multiple ways with CSS

Due to the company's business requirements, t...

Optimizing JavaScript and CSS to improve website performance

<br /> In the first and second parts, we int...

The difference between div and table in speed, loading, web application, etc.

1: Differences in speed and loading methods The di...

mysql server is running with the --skip-grant-tables option

The MySQL server is running with the --skip-grant...