Abstract: This article Chronicles my two experiences with Websocket. The first time, I stepped in a lot of holes. In the second practice, it can be said to be handy, but many theories are still lacking. Through this article, from theory to practice, all at one fell swoop.

directory

1. Websocket theory

(1) What is Websocket?

(2) The background of Websocket?

(3) The advantages of using this agreement?

(4) Handshake agreement

(5) What is the difference between Websocket and Socket?

(6) About socket.io

Ii. Vue realizes online chat (practice and stomp pit)

The Angular project home page pushes chart data in real time


1. Websocket theory

(1) What is Websocket?

Websocket is a network communication protocol. It is a full-duplex communication protocol over a single TCP connection.

WebSocket makes it easier to exchange data between the client and the server, allowing the server to proactively push data to the client. In the WebSocket API, a handshake between the browser and the server is all that is needed to create a persistent connection and two-way data transfer.

Full-duplex communication: It is also called bidirectional simultaneous communication. In this mode, two communication parties can send and receive information at the same time.

About the classification of the communication protocol, this article illustrated, is introduced in detail: blog.csdn.net/Dingjiawang…

(2) The background of Websocket?

Many websites use polling to implement push technology. Polling is when the browser makes an HTTP request to the server at a specific time interval (such as every second), and the server returns the latest data to the client browser. This traditional model has obvious disadvantages, that is, the browser needs to constantly send requests to the server, but THE HTTP request may contain long headers, in which the actual valid data may be only a small part, obviously this will waste a lot of bandwidth and other resources.

A relatively new technique for polling is Comet. This technique allows two-way communication, but still requires repeated requests. And long links, which are common in Comet, also consume server resources.

In this case, HTML5 defines the WebSocket protocol, can better save server resources and bandwidth, and can be more real-time communication.

(3) The advantages of using this agreement?

  • Less control overhead. The packet headers used for protocol control are relatively small when data is exchanged between the server and the client after the connection is created. Without extensions, this header size is only 2 to 10 bytes (depending on packet length) for server-to-client content; For client-to-server content, this header requires an additional 4-byte mask. This is a significant reduction in overhead compared to HTTP requests that carry a full header each time.
  • More real-time. Because the protocol is full-duplex, the server can proactively send data to the client at any time. Compared with THE HTTP request, which needs to wait for the client to initiate the request before the server can respond, the delay is significantly less; Even long polling comparisons like Comet can pass data more times in a short period of time.
  • Maintain the connection status. Unlike HTTP, Websocket requires a connection to be created first, which makes it a stateful protocol that can omit part of the state information when communicating later. HTTP requests, on the other hand, may need to carry status information (such as identity authentication, etc.) on each request.
  • Better binary support. Websocket defines binary frames and can handle binary content more easily than HTTP.
  • Extensions can be supported. Websocket defines extensions. Users can extend the protocol and implement some customized sub-protocols. For example, some browsers support compression.
  • Better compression. Compared to HTTP compression, Websocket, with appropriate extension support, can use the context of previous content, which can significantly improve compression rate when passing similar data.

(4) Handshake agreement

WebSocket is an application-layer protocol like HTTP, but it is a two-way communication protocol built on top of TCP.

Websocket handshakes using the 101 status code of HTTP/1.1.

To create a Websocket connection, a request is made through the browser and then the server responds, a process commonly known as handshaking.

Handshake process:

1. A TCP connection is established between the browser and the server and the three-way handshake is performed. This is the basis of communication, transmission control layer, if failed follow-up is not executed. 2. After the TCP connection is successful, the browser sends information such as the version number supported by WebSocket to the server through HTTP. (HTTP handshake before the start) 3. After receiving the handshake request from the client, the server also uses HTTP to feedback data. 4. After receiving the message indicating that the connection succeeds, transmit the communication over the TCP channel.

(5) What is the difference between Websocket and Socket?

Socket is an API of TCP and IP networks. It is an abstract layer to facilitate the use of TCP or UDP. It is a set of interfaces between the application layer and the transport layer.

(6) About socket.io

Socket.IO is a module of Node.js that provides a simple way to communicate via WebSockets. The WebSocket protocol is complex, and writing an application that supports WebSocket from scratch will take a lot of time. Socket.IO provides both server and client components, so it takes only one module to add WebSocket support to an application. Socket.IO also addresses browser support (not all browsers support WebSocket) and allows real-time communication across almost all commonly used browsers. Socket.IO is designed so well that bringing real-time communication into an application is simple. Nodejs and socket. IO are great options if you want to do anything that involves communication between the Web server and the browser.

# NPM install socket. Op $NPM install --save socketCopy the code

Ii. Vue realizes online chat (practice and stomp pit)

Requirements: Add the function of online chat between after-sales service personnel and customers in the background management system.

Framework: the Vue

Practice step 1: Connect webSocket and carry token

The webSocket connection methods I have encountered include the native way, which is as follows:

` initWebSocket () {/ / initializes the websocket const wsuri = 'WSS: / / XXXXXXXXXXXXXX/ws/adminOnlineService' enclosing websock = new WebSocket(wsuri) },`Copy the code

Step pit 1: For my project, this connection error 500, the reason is not carrying the token, this method carries the token way I know as follows: (1) send parameter, the disadvantage of this method is that every time send a message, will reconnect to the Websocket; Var WSS = new WebSocket(” WSS ://” + url? token + “/webSocketServer”); (3) Protocol header based: this. Websock = new WebSocket(WSURI, [‘Bearer’ + store.state.token]); After a trial, I think that no matter which way is adopted, we need to negotiate with the server, that is, what type of front-end transmission, back-end should use the corresponding treatment, do not easily negate any one way, this is a trial process. The reason for this is that the front end tries a lot of things, but finally decides to put it in the request address, at which point the server does the processing accordingly. Another way to connect to webSockets is to use socket.io-client

`onConnect: () => {
      console.log('connect')
      this.message = 'connect'
    },
    onDisconnect: () => {
      console.log('disconnect')
      this.message = 'disconnect'
    },
    connect: () => {
      let socket = io('wss://XXXXXXXXXXX', {
        path: '/welfare/ws/adminOnlineService',
        query: {
          'Authorization': 'Bearer  abdadfssadfasdf'
        }
      })
      socket.connect()
}`
Copy the code

This will bring the token to the request, but again the token will be spelled in the URL, requiring further processing by the server. The connection succeeds in this way, but the problem encountered is that after the connection succeeds, the connection will be broken, and then the connection will be immediately connected, so loop until the page is refreshed. The problem was not resolved. However, the native mode does not exist this problem, connect once.

Practice step 2: Make the WebSocket connection when you click the login button

Clicking the login button to connect to webSocket required defining the global method, which was vuEX at the time. It’s a long time ago, and it doesn’t seem to be necessary now, but let’s review how it was implemented.

In vuex modules we create a websocket.js file, which looks like this:

import store from './user' const state = { websock: null } const mutations = { STAFF_UPDATEWEBSOCKET (state, websock) { state.websock = websock } // STAFF_SEND (state, Text) {// state.websock.send(text) //}} Need to carry parameter token const actions = {// Use ES2015 parameter destruct to simplify code (especially if we need to call commit many times) STAFF_WEBSOCKET ({commit}) {let token = encodeURI('Bearer ' + store.state.token) const wsuri = 'wss://XXXXXXXXX/? Authorization=' + token + '&EIO=3&transport=websocket' commit('STAFF_UPDATEWEBSOCKET', New WebSocket(wSURi)) // Only when the onOpen method is defined can the implementation continue to receive messages, i.e. the onMessage method is called where it is used. State.websock. Onopen = function () {} // Heartbeat packet, Heartbeat setInterval(function () {state.websock. Send (json.ify ({'heart': True}))}, 30000)}} It will be found that the writing here is similar to that in Mutations. However, to use return, the relevant data needs to be written in getters. const getters = { STAFF_UPDATE (state) { return state.websock } } export default { state, mutations, actions, getters }Copy the code

Related code comments are already reflected in the above code and are used in the following code:

1. Websocket send method is called, that is, click send, will call the send method, will send the message to the server, the following code is for different definitions, take different methods, for example, the third method is getters; The second method is to obtain the STAFF_SEND method for the annotations in mutations; The first is to get the method defined in actions.

At first glance, it seems unnecessary. Wouldn’t it be more convenient for us to just distribute mutation? In fact, no, remember that mutation must execute this restriction synchronously? Action is free! We can perform asynchronous operations within an action

$store.dispatch('STAFF_WEBSOCKET') // This.store.com MIT ('STAFF_SEND').send(' this is the message from the client ').this.store.getters.staff_update.send (' SDFSFS ')Copy the code

Actions supports the same payload and object distribution:

// Distribute as a payload
store.dispatch('incrementAsync', {
  amount: 10
})

// Distribute as objects
store.dispatch({
  type: 'incrementAsync'.amount: 10
})
Copy the code

2. Receive the message from the server through WebSocket. The implementation method is as follows:

onmessage () {
  let that = this
  this.$store.getters.STAFF_UPDATE.onmessage = function (evt) {
  let message = JSON.parse(evt.data)
  that.messages.push({
     content: message.content,
     self: false
  })
 }
}
Copy the code

The key is to get the onMessage method from getters. As emphasized above, you need to implement the onOpen method before calling this method.

As above, you can implement chat.

Practice Step 3: WebSocket events and methods

Var socket = new WebSocket(" URL "); var socket = new WebSocket(" URL "); // use ws:// in the url instead of http://; Socket. onOpen = function(){alert(" Established "); } socket. Onerror = function(){alert("error!"); ); } socket. Onclose = function(){alert("closed!"); ); } // The json object should be serialized to the JSON string socket.send(STR); Socket. Onmessage = function(event){console.log(event.data); } // Call close() to close the Web Sockets connection. Call close() to socket.close() at any time;Copy the code

The Angular project home page pushes chart data in real time

In the context of Websocket, the reasons for Websocket’s emergence are introduced. In fact, this is why the requirement used the solution in this project. In other projects contacted, the page will also be refreshed in real time, and nearly 10 interfaces will be requested every once in a while. In this demand, the data volume is larger and the request interface volume is more, so this method is adopted.

The following is the implementation code, in fact, the use of the process is the same, mainly depends on the business logic.

initWebSocket() { const url = '*******'; const ws = new WebSocket(url); ws.onopen = () => { this.clearWS(); this.ws = ws; Ws.onmessage = evt => {// The following is the business logic const data = json.parse (evt.data); if (this.simpleMode) { this.reciveFromWs4Simple(data); } else { this.reciveFromWs(data); }}; ws.onclose = () => { this.clearWS(); }; ws.onerror = () => { this.clearWS(); }; }; } / / private clearWS() {const ws: WebSocket = this.ws; if (ws) { ws.onclose = null; ws.onopen = null; ws.onmessage = null; } this.ws = null; } /** * change the logic of heartbeat monitoring whether the connection is down. */ private heartbeat() {this.reconnectTimer = window.setInterval() => {const ws: WebSocket | null = this.ws; if (! this.isWSAvailable(ws)) { this.reConnect(); }}, 10000); } / / private reConnect() {console.warn(' reConnect '); this.clearWS(); this.initWebSocket(); } sendByWs(data) { const ws = this.ws; if (! Ws) {console.warn('[WS - failed to send data]: Websocket not ready or disconnected '); return; } switch (ws.readyState) {case webSocket. CONNECTING: console.warn('[WS - failed to send data]: WebSocket CONNECTING... '); break; case WebSocket.OPEN: ws.send(JSON.stringify(data)); break; Default: console.warn('[WS - failed to send data]: Websocket is about to disconnect or has disconnected '); } } switchLive(live) { this.live = live; const name = 'live'; this.sendByWs({ name, live }); } ngOnDestroy() {this.ws && this.ws. Close (1000, 'the user has left the current page or a page refresh occurred '); this.reConnectTimer && clearInterval(this.reConnectTimer); }Copy the code