主頁 > 企業開發 > WebSocket學習總結

WebSocket學習總結

2020-09-24 07:09:31 企業開發

  本文隨便寫了點自己對WebSoket通訊協議理解,在兩種框架上玩的Demo,然后踩了幾個坑還有沒填上的坑(歡迎評論指導一下),

 

WebSocket是什么?使用WebSocket的原因?

  WebSocket是網路通訊協議的一種,

  提到網路通訊協議,我第一個就想到了HTTP協議,但是HTTP協議的一些特性我想不用多說,大家也都是了解的,像無法保持長連接(由于功能需要,已有大佬整出保持長連接的方式);發起端只能是客戶端;這些特性讓我們在實際開發某些功能遇到了極大的麻煩,所以在HTML5推出WebSocket標準,讓瀏覽器和服務器建立了無限制的雙全工通信,雙方可以互發訊息,

 

WebSocket框架上使用

  angular(7.2.2)+ ionic(4.0.0)

  這是一個移動端應用程式,在angular框架中,我慣用服務(service)來處理業務,因此直接在服務管理的檔案夾創建一個WebSocket的服務(ng generate service WebSocket),WebSocket服務里包含創建連接,重連機制,心跳檢測,計算運行時間等基礎功能(詳細寫法可見代碼),

  接下來可以在app全域新增一個WebSocket組件,ngOnInit生命鉤子去建立連接,往組件中寫入收發訊息代碼,會解決網頁重繪導致WebSocket實體被清除,WebSocket組件在生命周期再次連接,

  問題1:我在ionic中創建了WebSocket組件,用于重繪重連(app沒有重繪,實際操作只會在瀏覽器除錯中出現),在瀏覽器上除錯可以正常使用并且不會斷開連接,但是當我將代碼打包編譯成apk后,打開程式會出現白屏?

  問題2:因為我脫離了組件使用WebSocket,單純的呼叫服務,我實際組件中需要使用的資料也保存在服務之中,導致訊息回傳資料不會更新視圖?

  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通訊物件
  9   url: string = null;                                 // websocket連接地址
 10   isConnectSuccess: boolean = false;                  // 當前連接狀態
 11   isReconnect: boolean = false;                       // 是否正在重連
 12   reconnectSubscription: any = null;                  // 定時重新連接物件
 13   reconnectPeriod: number = 20 * 1000;                // 重連失敗,定時重新連接的時間刻度,20s
 14   heartCheckSubscription: any = null;                 // 定時心跳檢查物件
 15   heartCheckPeriod: number = 10 * 60 * 1000;          // 定時心跳檢測的時間刻度,10min
 16   runTimeSubscription: any = null;                    // 記錄運行時間物件
 17   runTimePeriod: number = 10 * 60 * 1000;             // 記錄運行時間的時間刻度,10min
 18 
 19   constructor(
 20 private messageService: MessageService,
 21   ) { }
 22 
 23   /**
 24    * @description 更新連接地址,創建WebSocket實體,添加連接打開,連接關閉,連接例外,接收訊息事件
 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('當前設備沒有服務器地址');
 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 檢測當前websocket服務狀態
 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       // 沒有連接
 66       break;
 67     case 1:
 68       // 連接成功
 69       break;
 70     case 2:
 71       // 連接正在關閉
 72       break;
 73     case 3:
 74       // 連接關閉
 75       break;
 76   }
 77 } else {
 78   // WebSocket實體物件沒有,重繪瀏覽器會導致這種情況
 79 }
 80   }
 81 
 82   /**
 83    * @description WebSocket連接成功時觸發事件,當前連接狀態改為成功,如果當前正在重連則停止重新連接,開啟心跳檢測和計算連接運行時間
 84    * @param event 連接成功時,服務端發回的事件物件
 85    * @method OnOpen
 86    * @author chenkun
 87    */
 88   OnOpen(event: any) {
 89 // 連接成功
 90 this.isConnectSuccess = true;
 91 if (this.isReconnect) {
 92   this.StopReconnect();
 93   this.StartHeartCheck();
 94   this.StartCalcRunTime();
 95 }
 96   }
 97 
 98   /**
 99    * @description WebSocket連接關閉時觸發事件,當前連接狀態改為失敗,開始嘗試重新連接,停止計算運行時間
100    * @param event 連接失敗時,服務端發回的事件物件
101    * @method OnClose
102    * @author chenkun
103    */
104   OnClose(event: any) {
105 // 連接關閉
106 this.isConnectSuccess = false;
107 this.websocket.close();
108 this.StartReconnect();
109 this.StopRunTime();
110   }
111 
112   /**
113    * @description WebSocket連接例外時觸發事件,出現例外會同時觸發連接關閉事件
114    * @param event 連接例外時,服務端發回的事件物件
115    * @method one rror
116    * @author chenkun
117    */
118   one rror(event: any) {
119 // 連接例外
120 this.isConnectSuccess = false;
121   }
122 
123   /**
124    * @description WebSocket服務端發回訊息接收事件
125    * @param event 服務端發回訊息的事件物件
126    * @method OnMessage
127    * @author chenkun
128    */
129   OnMessage(event: any) {
130  // 服務器回傳的訊息
131     console.log(event);
132   }
133 
134   /**
135    * @description WebSocket客戶端發送訊息給服務端,發送訊息前先檢查列印服務是否連接
136    * @param message 客戶端發送的訊息
137    * @method SendMessage
138    * @author chenkun
139    */
140   SendMessage(message: any) {
141 // 檢查WebSocket的狀態,連接存在時才能發送訊息
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 開始定時重連WebSocket服務端,如果連接成功,停止重連并且退出,如果正在重連直接退出
152    * 如果都沒有,改為正在重連狀態,訂閱計時器回圈發送呼叫連接
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(`重連:${value}次`);
167   const url = this.url;
168   this.Connect(url);
169 });
170   }
171 
172   /**
173    * @description 更改不再重連狀態,取消訂閱計時器回圈發送重復連接
174    * @method StopReconnect
175    * @author chenkun
176    */
177   StopReconnect() {
178 this.isReconnect = false;
179 // 取消訂閱定時重新連接事件
180 if (typeof this.reconnectSubscription !== 'undefined' && this.reconnectSubscription != null) {
181   this.reconnectSubscription.unsubscribe();
182 }
183   }
184 
185   /**
186    * @description 訂閱計時器查詢心跳檢測,如果當前處于連接成功狀態不做處理,如果沒有連接,就停止心跳檢測,開始重新連接
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, '連接狀態成功,發送訊息保持連接');
194   } else {
195     this.StopHeartCheck();
196     this.StartReconnect();
197   }
198 });
199   }
200 
201   /**
202    * @description 取消訂閱計時器查詢心跳檢測
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 訂閱計時器計算連接運行時間
214    * @method StartCalcRunTime
215    * @author chenkun
216    */
217   StartCalcRunTime() {
218 this.runTimeSubscription = interval(this.runTimePeriod).subscribe(value =https://www.cnblogs.com/chenkun-code/p/> {
219   console.log('運行時間', `${value}分鐘`);
220 });
221   }
222 
223   /**
224    * @description 取消訂閱計時器計算連接運行時間
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)

  Vue專案中,直接創建一個SocketHelper.vue的子組件,并且直接在App.vue引入組件,借助Vuex來傳遞資料,借助eventBus收發訊息事件,

<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: {
    //初始化weosocket
    initWebSocket() {
      const url = "ws:" + this.configs.ServiceAddress + ":40100"; //ws地址
      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() {
      // 連接成功
    },

    websocketonerror(e) {
      // 連接例外
    },

    websocketclose(e) {
      // 連接關閉
      this.initWebSocket();
    },

    websocketonmessage(e) {
      // 接收訊息
    },

    websocketsend(agentData) {
      // 發送訊息
      if (this.websocket.readyState === 1) {
        this.websocket.send(agentData);
      }
    },

  }
};
</script>

 

參考來自

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

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/117318.html

標籤:JavaScript

上一篇:html與css注意事項及小知識點

下一篇:JS事件總結

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more