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