WebSocket learning summary

Keywords: Javascript Vue angular socket network

This article casually wrote about my own understanding of websocket communication protocol, Demo played on two frameworks, and then stepped on several pits and unfilled pits (welcome to comment and guide).

 

What is WebSocket? Why use WebSocket?

WebSocket is a kind of network communication protocol.

When it comes to network communication protocol, I first think of HTTP protocol, but I don't need to say much about some features of HTTP protocol, which we all know, such as the inability to maintain a long connection (due to the functional needs, there is a way for the big guy to maintain a long connection); the initiator can only be the client; these features cause us great trouble in the actual development of some functions , so we launched WebSocket standard in HTML5, which allows browser and server to establish unlimited dual industry communication, and both sides can send messages to each other.

 

Use on WebSocket framework

  angular(7.2.2)+ ionic(4.0.0)

This is a mobile application. In the angular framework, I usually use services to handle business, so I create a WebSocket service (ng generate service WebSocket) directly in the service management folder. WebSocket service includes basic functions such as connection creation, reconnection mechanism, heartbeat detection, calculation of running time (see code for detailed writing method).

Next, you can add a WebSocket component in the app global. The ngOnInit life hook establishes the connection and writes the receiving and sending message code to the component. It will solve the problem that the WebSocket instance is cleared due to web page refresh, and the WebSocket component connects again in the life cycle.

Question 1: I created WebSocket component in ionic to refresh and reconnect (app does not refresh, but actual operation will only appear in browser debugging). Debugging on browser can work normally and will not disconnect. But when I package the code and compile it into apk, a white screen will appear when I open the program?

Question 2: because I use WebSocket instead of components and simply call services. The data that I need to use in the actual component is also saved in the service, so that the message return data will not update the view?

  1 import { Injectable } from '@angular/core';
  2 import { interval, Subject } from 'rxjs';
  3 
  4 @Injectable({
  5   providedIn: 'root'
  6 })
  7 export class WebsocketService {
  8   public websocket: WebSocket;                        // websocket Communication object
  9   url: string = null;                                 // websocket Connection address
 10   isConnectSuccess: boolean = false;                  // Current connection status
 11   isReconnect: boolean = false;                       // Is reconnection in progress
 12   reconnectSubscription: any = null;                  // Periodically reconnect objects
 13   reconnectPeriod: number = 20 * 1000;                // Reconnect failed, timed reconnect timescale, 20 s
 14   heartCheckSubscription: any = null;                 // Timed heartbeat check object
 15   heartCheckPeriod: number = 10 * 60 * 1000;          // Time scale for timed heartbeat detection, 10 min
 16   runTimeSubscription: any = null;                    // Record runtime object
 17   runTimePeriod: number = 10 * 60 * 1000;             // Time scale for recording operation time, 10 min
 18 
 19   constructor(
 20 private messageService: MessageService,
 21   ) { }
 22 
 23   /**
 24    * @description Update connection address, create WebSocket instance, add connection open, connection close, connection exception, receive message event
 25    * @method Connect
 26    * @author chenkun
 27    */
 28   Connect(url?: string) {
 29 const ip = localStorage.getItem('ipAddress');
 30 if (ip) {
 31   this.url = "ws://" + ip + ":40100";
 32 } else {
 33   this.messageService.ErrorToast('The current device does not have a server address');
 34 }
 35 if (!!url) {
 36   this.url = url;
 37 }
 38 if (this.url) {
 39   this.websocket = new WebSocket(this.url);
 40 }
 41 this.websocket.onopen = (event) => {
 42   this.OnOpen(event);
 43 }
 44 this.websocket.onclose = (event) => {
 45   this.OnClose(event);
 46 }
 47 this.websocket.onerror = (event) => {
 48   this.OnError(event);
 49 }
 50 this.websocket.onmessage = (event) => {
 51   this.OnMessage(event);
 52 }
 53   }
 54 
 55   /**
 56    * @description Check the current websocket service status
 57    * @method CheckWebSocket
 58    * @author chenkun
 59    */
 60   CheckWebSocket() {
 61 const websocket = this.websocket;
 62 if (websocket) {
 63   switch (websocket.readyState) {
 64     case 0:
 65       // No connection
 66       break;
 67     case 1:
 68       // Successful connection
 69       break;
 70     case 2:
 71       // Connection closing
 72       break;
 73     case 3:
 74       // Connection closure
 75       break;
 76   }
 77 } else {
 78   // WebSocket Instance object does not, refreshing browser will cause this situation
 79 }
 80   }
 81 
 82   /**
 83    * @description WebSocket Event triggered when the connection is successful. The current connection status changes to successful. If the connection is currently reconnecting, stop reconnecting, start heartbeat detection and calculate the connection running time
 84    * @param event Event object sent back by the server when the connection is successful
 85    * @method OnOpen
 86    * @author chenkun
 87    */
 88   OnOpen(event: any) {
 89 // Successful connection
 90 this.isConnectSuccess = true;
 91 if (this.isReconnect) {
 92   this.StopReconnect();
 93   this.StartHeartCheck();
 94   this.StartCalcRunTime();
 95 }
 96   }
 97 
 98   /**
 99    * @description WebSocket Event triggered when the connection is closed. If the current connection status changes to failed, try to reconnect and stop calculating the running time
100    * @param event Event object sent back by the server when the connection fails
101    * @method OnClose
102    * @author chenkun
103    */
104   OnClose(event: any) {
105 // Connection closure
106 this.isConnectSuccess = false;
107 this.websocket.close();
108 this.StartReconnect();
109 this.StopRunTime();
110   }
111 
112   /**
113    * @description WebSocket Event is triggered when the connection is abnormal. If an exception occurs, the connection close event will be triggered at the same time
114    * @param event Event object sent back by the server when the connection is abnormal
115    * @method OnError
116    * @author chenkun
117    */
118   OnError(event: any) {
119 // Connection exception
120 this.isConnectSuccess = false;
121   }
122 
123   /**
124    * @description WebSocket Message receiving event sent back by the server
125    * @param event Event object sent back by the server
126    * @method OnMessage
127    * @author chenkun
128    */
129   OnMessage(event: any) {
130  // Messages returned by the server
131     console.log(event);
132   }
133 
134   /**
135    * @description WebSocket The client sends the message to the server. Before sending the message, check whether the printing service is connected
136    * @param message Messages sent by clients
137    * @method SendMessage
138    * @author chenkun
139    */
140   SendMessage(message: any) {
141 // inspect WebSocket Can send messages only when the connection exists
142 this.CheckWebSocket();
143 if (this.websocket) {
144   if (this.websocket.readyState === 1) {
145     this.websocket.send(message);
146   }
147 }
148   }
149 
150   /**
151    * @description Start regular reconnection of WebSocket server. If the connection is successful, stop reconnection and exit. If reconnection is in progress, exit directly
152    * If none, change to reconnecting status, and the subscription timer cycles to send the call connection
153    * @method StartReconnect
154    * @author chenkun
155    */
156   StartReconnect() {
157 if (this.isConnectSuccess) {
158   this.StopReconnect();
159   return;
160 }
161 if (this.isReconnect) {
162   return;
163 }
164 this.isReconnect = true;
165 this.reconnectSubscription = interval(this.reconnectPeriod).subscribe(async (value) => {
166   console.log(`Reconnect:${value}second`);
167   const url = this.url;
168   this.Connect(url);
169 });
170   }
171 
172   /**
173    * @description Change no longer reconnection status, unsubscribe timer cycle send duplicate connection
174    * @method StopReconnect
175    * @author chenkun
176    */
177   StopReconnect() {
178 this.isReconnect = false;
179 // Unsubscribe scheduled reconnect events
180 if (typeof this.reconnectSubscription !== 'undefined' && this.reconnectSubscription != null) {
181   this.reconnectSubscription.unsubscribe();
182 }
183   }
184 
185   /**
186    * @description The subscription timer queries the heartbeat detection. If it is currently in the status of connection success, it will not be processed. If there is no connection, stop heartbeat detection and start to reconnect
187    * @method StartHeartCheck
188    * @author chenkun
189    */
190   StartHeartCheck() {
191 this.heartCheckSubscription = interval(this.heartCheckPeriod).subscribe((value) => {
192   if (this.websocket != null && this.websocket.readyState === 1) {
193     console.log(value, 'Connection status successful, send message to keep connection');
194   } else {
195     this.StopHeartCheck();
196     this.StartReconnect();
197   }
198 });
199   }
200 
201   /**
202    * @description Unsubscribe timer query heartbeat detection
203    * @method StopHeartCheck
204    * @author chenkun
205    */
206   StopHeartCheck() {
207 if (typeof this.heartCheckSubscription !== 'undefined' && this.heartCheckSubscription != null) {
208   this.heartCheckSubscription.unsubscribe();
209 }
210   }
211 
212   /**
213    * @description Subscription timer calculates connection run time
214    * @method StartCalcRunTime
215    * @author chenkun
216    */
217   StartCalcRunTime() {
218 this.runTimeSubscription = interval(this.runTimePeriod).subscribe(value => {
219   console.log('Running time', `${value}Minute`);
220 });
221   }
222 
223   /**
224    * @description Unsubscribe timer calculates connection run time
225    * @method StopRunTime
226    * @author chenkun
227    */
228   StopRunTime() {
229 if (typeof this.runTimeSubscription !== 'undefined' && this.runTimeSubscription !== null) {
230   this.runTimeSubscription.unsubscribe();
231 }
232   }
233 }

  vue(2.5.2)+ element-ui(2.4.11)

In the Vue project, a subcomponent of SocketHelper.vue is created directly, and components are imported directly in App.vue. Vuex is used to transmit data and eventBus is used to send and receive message events.

<template>
  <div id="app" class="app">
    <socket />
    <router-view />
  </div>
</template>

<script>
import socket from "./public-components/SocketHelper.vue";
export default {
  name: "App",
  components: {
    socket
  },
};
</script>

 

<template>
  <div></div>
</template>

<script>
import store from "../vuex/store";

export default {
  data() {
    return {
      websocket: null,
      eventBus: this.store.state.eventBus
    };
  },

  created() {
    this.initWebSocket();
  },

  destroyed() {
    this.websocketclose();
  },

  methods: {
    //Initialization weosocket
    initWebSocket() {
      const url = "ws:" + this.configs.ServiceAddress + ":40100"; //ws address
      this.websocket = new WebSocket(url);
      this.websocket.onopen = this.websocketonopen;
      this.websocket.onerror = this.websocketonerror;
      this.websocket.onclose = this.websocketclose;
      this.websocket.onmessage = this.websocketonmessage;
      this.eventBus.$off("WebSocketSendContent");
      this.eventBus.$on("WebSocketSendContent", res => {
        this.websocketsend(res);
      });
    },

    websocketonopen() {
      // Successful connection
    },

    websocketonerror(e) {
      // Connection exception
    },

    websocketclose(e) {
      // Connection closure
      this.initWebSocket();
    },

    websocketonmessage(e) {
      // receive messages
    },

    websocketsend(agentData) {
      // send message
      if (this.websocket.readyState === 1) {
        this.websocket.send(agentData);
      }
    },

  }
};
</script>

 

Reference from

[angular integration websocket] https://www.jianshu.com/p/b04c34df128d

Posted by redmonkey on Fri, 17 Apr 2020 02:42:03 -0700