I met webScoket

Generally, HTTP is used for network communication between front end and back end. However, HTTP has a defect that communication can only be initiated by the client. For example:

Front-end display user name: the client sends a request to the server data returned by the server, but users if you change your user name when the client does not automatically update data, takes the client request to the server again refresh the page to update the data, so how can you make the server to the client push data, real-time automatic updates to show the client data? If HTTP protocol is used, polling can be used (that is, every once in a while the client sends a request to the server to check whether the server data is updated), so it is a waste of resources can not be taken, we can use WebSocket to solve this problem, similar to the chat room mobile phone scan code login situation

WebSocket is a network communication protocol. The biggest feature of WebSocket is that the server can actively push data to the client, and the client can also actively push data to the server. It is a summary of the characteristics of server push technology:

  1. Built on top of TCP
  2. In HTTP protocol has good compatibility, the default port is 80 and 443, and the handshake phase uses HTTP protocol, so it is not easy to shield the handshake, can pass a variety of HTTP proxy server
  3. The data format is relatively light, with low performance overhead and high communication efficiency
  4. Without the same-origin policy address, clients can communicate with any server
  5. You can send text or binary data
  6. The protocol identifier is WS/WSS, and the server URL is the URL

Used in front-end development

The WebScoket constructor is provided by the browser and is used to create a new WebSocket instance

const ws = new WebSocket('wss://echo.websocket.org')
ws.onopen = function(evt) { 
  console.log("Connection successful...")
  ws.send("Hello web sockets!")}; ws.onmessage =function(evt) {
  console.log(get sent messages,evt) ws.close()}; ws.onclose =function(evt) {
  console.log("Disconnect the connection.")}Copy the code

Commonly used API

webSocket.onopen

The nopen property of the instance object, used to specify the callback function after a successful connection

ws.onopen = function(evt) { 
  console.log("Connection successful...")
  ws.send("Hello web sockets!")};Copy the code

If you want to specify multiple callback functions, you can use addEventListener

ws.addEventListener('open'.function (event) {
  ws.send('Hello Server! ')});Copy the code

webSocket.readyState

Gets the current state of the instance object

  • CONNECTING: The value is 0, indicating that a connection is being established
  • OPEN: if the value is 1, the connection is successful. Can communication
  • CLOSEING: A value of 2 indicates that the connection is being closed
  • CLOSED: the value is 3, and the connection is CLOSED or fails to be opened
console.log(ws.readState)
Copy the code

webSocket.onclose

The onclose property of the instance object, used to specify; If you want to specify multiple callback functions, you can also use ‘addEvenlistener

ws.onclose = function(event) {
  const code = event.code
  const reason = event.reason
  const wasClean = event.wasClean

}

Copy the code

webSocket.onmessage

If you want to specify multiple callback functions, you can also use addEvenlistener to note that the returned data format may be text that can be converted from json.parse (), or binary data

ws.onmessage = function(event) {
  let data = event.data;
  consoole.log('Data sent by the server',data)
};
Copy the code

webSocket.send()

The send() method of the instance object is used to send data to the server.

ws.send('your message');
Copy the code

webSocket.onerror

The onError property of the instance object, which specifies the callback function when an error is reported

socket.onerror = function(event) {
  // handle error event
};

socket.addEventListener("error".function(event) {
  // handle error event
});
Copy the code

Vue project encapsulation for use

Break line reconnection

We will analyze two causes of disconnection

  1. No webSocket timeout message automatically disconnects
  2. Websocket exceptions include server interruptions, interactive screen cuts, and other client interruptions

Determine if you are online

  1. When the client sends the request to the server for the first time, it carries the unique identifier and time stamp. The server queries the unique identifier of the request to the DB or cache, and stores it in the DB or cache if it does not exist
  2. When the client sends the request to the server for the first time, it carries the unique identifier and time stamp. The server queries the unique identifier of the request to the DB or cache, and stores it in the DB or cache if it does not exist
  3. The resulting number of milliseconds determines whether it is greater than the specified time. If it is less than the specified time, it is online; otherwise, it is offline

Solve the disconnection problem

  • No webSocket timeout message automatically disconnects

Solution: According to the timeout period set by the server, send heartbeat packets within the timeout period

In the next timer, an empty packet is sent to the client at a certain interval, and the client feeds back the same empty packet. If the server does not receive the feedback packet sent by the client within a certain period of time, it can only be considered as offline

The heartbeat package: Analogy to the heartbeat every send a fixed time, to tell the server to the client still has maintained a long connection, the content of this package are no special rules, can according to the project, the client is the server completes the consultation, exist in the TCP mechanism of heartbeat packets, SO_KEEPALIVE in TCP’s option, the system default setting is 2 small When the heartbeat frequency, but can not detect machine power, network cable pulled out, firewall these disconnections, generally can be used to keep alive

We can use webSocket to send heartbeat packets. Heartbeat detection means that the client periodically sends messages to the server, which proves that the client is online. If the client does not send messages after a certain period of time, it is disconnected.

  1. The client sends a probe packet to the server at regular intervals
  2. The client starts a timeout timer when sending packets
  3. The server receives a packet and should respond with a packet
  4. If the client receives a reply packet from the server, the server is running properly and the timeout timer is deleted
  5. If the client timeout timer times out and no reply packet is received, the server hangs up

  heartCheck() {
    // The timing of the heartbeat mechanism can be agreed with the back end
    this.pingPong = 'ping'// The heartbeat mechanism status of the ws
    this.pingInterval = setInterval(() = > {
      if (this.ws.readyState === 1) {
        // check that ws is in a linked state before sending
        this.ws.send('ping'); // The client sends ping}},10000)
    this.pongInterval = setInterval(() = > {
      if (this.pingPong === 'ping') {
        this.closeHandle('pingPong has not changed to pong'); // No pong is returned and webSocket restarts
      }
      // Reset to ping if the next ping fails or pong fails to return (pingPong will not be changed to pong), the system will restart
      console.log('return to pong')
      this.pingPong = 'ping'
    }, 20000)}Copy the code
  • Websocket exceptions include server interruption, interactive screen cutting, and other client exceptions

Reconnecting: close the connection through onclose, and clear the data stored on the server when it gets online again. We can introduce reconnecting-websocket.min.js, ws, and js library API methods.

const ws = new ReconnectingWebSocket(url);
// Reconnection:
reconnectSocket(){
   if ('ws' in window) {
       ws = new ReconnectingWebSocket(url);
   } else if ('MozWebSocket' in window) {
      ws = new MozWebSocket(url);
   } else {
     ws = newSockJS(url); }}Copy the code

Js library: offline.min.js is supported for network outage monitoring

onLineCheck(){
   Offline.check();
   console.log(Offline.state,'---Offline.state');
   console.log(this.socketStatus,'---this.socketStatus');

   if(!this.socketStatus){
       console.log('Network connection is down! ');
       if(Offline.state === 'up' && websocket.reconnectAttempts > websocket.maxReconnectInterval){
           window.location.reload();
       }
       reconnectSocket();
   }else{
       console.log('Network connection successful! ');
       websocket.send("heartBeat"); }}// Use: calls network interruption monitoring when webSocket disconnects
websocket.onclose => () {
   onLineCheck();
};

Copy the code

In-project encapsulation

  • Create the socket.js file

Used to create a global WS class that creates different webSocket instances in each component by passing different parameters

class WebSocketClass {
  constructor(url) {
    this.instance = null
    this.connect(url,param)
  }
  static getInstance() {
    if (!this.instance) {
      this.instance = new WebSocketClass()
    }
    return this.instance
  }

  connect(url,param) {
    // URL Long connection address, param: parameter sent to the server during connection, which can be used for authentication on the server
    this.ws = new WebSocket(`${url}/${cookie}`)
    this.ws.onopen = e= > {
      this.status = 'open'

      console.log('Connection successful', e)
      this.heartCheck()
      this.getMessage()
    }
  }

  heartCheck() {
    // The timing of the heartbeat mechanism can be agreed with the back end
    this.pingPong = 'ping'// The heartbeat mechanism status of the ws
    this.pingInterval = setInterval(() = > {
      if (this.ws.readyState === 1) {
        // check that ws is in a linked state before sending
        this.ws.send('ping'); // The client sends ping}},10000)
    this.pongInterval = setInterval(() = > {
      if (this.pingPong === 'ping') {
        this.closeHandle('pingPong has not changed to pong'); // No pong is returned and webSocket restarts
      }
      // Reset to ping if the next ping fails or pong fails to return (pingPong will not be changed to pong), the system will restart
      console.log('return to pong')
      this.pingPong = 'ping'
    }, 20000)}closeHandle(e = 'err') {
    // Since webSocket is unstable, you can only close it manually (call closeMyself) or reconnect it
    if (this.status ! = ='close') {
      console.log(Disconnect and reconnect to websocket, e)
      if (this.pingInterval ! = =undefined && this.pongInterval ! = =undefined) {
        // Clear the timer
        clearInterval(this.pingInterval)
        clearInterval(this.pongInterval)
      }
      this.connect(); / / reconnection
    } else {
      console.log('WebSocket manually closed, or connecting')}}getMessage() {
    this.ws.onmessage = e= > {
      if (e.data === 'pong') {
        this.pingPong = 'pong'// Go back to pong on the server and modify the status of pingPong
      } else{}console.log(e.data)
      return e.data
    }
  }

  close() {
    clearInterval(this.pingInterval)
    clearInterval(this.pongInterval)
    this.status = 'close'
    this.ws.send('close')
    this.ws.close()
  
    console.log('close')}}export default  WebSocketClass
Copy the code

Used in components

xxx.vue

import sokect from './socket.js'.method:{
    initSocket () {
        this.socketObj = new socket('wss://xxxx/message',data)
    }
}

Copy the code

The principle of analysis

How to do that?

Because WebSocket is based on TCP communication, a WebSocket long connection is essentially a TCP long connection. Because TCP itself is a persistent connection, through the three-way handshake in the operating system kernel memory summary maintenance of quad objects (source IP, source port, destination IP, destination port) to establish a connection,TCP connection is a communication between the two parties to decide when to end the communication, so TCP is naturally a persistent connection,WebSocket protocol to achieve exclusive A TCP channel that is responsible for determining message boundaries from the TCP liu and resolving each individual message packet. It supports full-duplex bidirectional communication and maintains the connection status of the intermediate network without affecting the Application through PING/PON Frame packets.

WebSocket connection process

  1. The client initiates an HTTP request and establishes a TCP connection after three handshakes. The HTTP request stores information about the Version supported by Websocket, such as Upgrade, Connection, and websocket-version
Connection: Upgrade
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: IRQYhWINfX5Fh1zdocDl6Q==
Sec-WebSocket-Version: 13
Upgrade: websocket

Copy the code
  • Connection: Upgrade Indicates that the protocol is to be upgraded.

  • Upgrade: Websocket needs to be upgraded to the Websocket protocol.

  • Sec-websocket-extensions: Indicates Extensions (such as message compression plug-ins) that the client wants to execute.

  • Sec-websocket-key: verifies the WebSocket protocol. It corresponds to the sec-websocket-accept of the server response header.

  • Sec-websocket-version: indicates the WebSocket Version. If the server does not support the version, you need to return an sec-websocket-versionheader containing the version number supported by the server.

  1. After receiving the handshake request from the client, the server also uses HTTP to send back data

The HTTP Header that the server responds to is as follows:

Connection: upgrade
Sec-Websocket-Accept: TSF8/KitM+yYRbXmjclgl7DwbHk=
Upgrade: websocket

Copy the code
  • Connection: Upgrade Indicates that the protocol is to be upgraded.

  • Upgrade: Websocket needs to be upgraded to the Websocket protocol.

  • Sec-websocket-accept: indicates the value generated by sec-websocket-key. The value is returned to the client for the client to verify that the server supports Websocket.

  1. When the client receives the message that the connection is successful, it initiates full-duplex communication through the TCP transport channel

conclusion

After studying WebSocket, I have a deep understanding of the following points:

  • WebSocket is an application layer protocol specifically designed to provide full duplex between Web applications and servers.
  • Both WebSocket and HTTP are implemented based on TCP. WebSocket uses HTTP to establish connections, but it defines a new set of header fields that are not used in HTTP to create and destroy TCP requests frequently. Reduce the occupation of network bandwidth resources and save server resources.
  • There are no same-origin restrictions, and clients can communicate with any server. WebSocket data frames are in order.
  • WebSocket is purely event-driven, and once a connection is established, it listens for events to handle incoming data and changing connection state, all in the form of a sequence of frames. After the server sends the data, messages and events arrive asynchronously.

In short, websockets are a tiny transport layer built on top of the device’S TCP/IP stack. The goal is to provide Web application developers with a basic TCP communication layer that is as close to native as possible, while adding abstractions to eliminate some possible compatibility with the way the Web works.