成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

走進數據通信之 Websocket

網絡 通信技術
最近在做一個可視化拖拽搭建 H5 頁面的項目,整個項目分為 后臺配置應用 和 前臺渲染應用。其中一個業務場景是要求配置頁面的同時,前臺渲染應用能夠同步將配置渲染出來。

[[441666]]

一、寫在前面

最近在做一個可視化拖拽搭建 H5 頁面的項目,整個項目分為 后臺配置應用 和 前臺渲染應用。其中一個業務場景是要求配置頁面的同時,前臺渲染應用能夠同步將配置渲染出來。換句話說,你在后臺配置這個頁面背景色是紅色,那么前臺應用無須刷新頁面等操作背景色就自動變為紅色。

這個需求的核心是保持兩個前端應用的數據實時同步,換句話說也就是兩個前端應用之間的通信。

乍一看這個需求,第一時間想到的是 iframe ,將應用2內嵌到應用1中,然后調用 window.postMessage() 進行數據通信。但是使用 iframe 存在兼容性問題,坑太多。另外對于不存在嵌套關系的兩個應用來說,強行進行嵌套會讓后續開發者無法理解。

到了這里,我淺薄的知識量不知道還有什么其他方法,選擇了直接看答案!之前開發的同事選擇了 WebSocket 實現前后臺之間的數據同步。彷佛一道閃電,擊碎了桎梏,劈開了新世界的大門。(是我知識積累太淺薄了,嗚嗚嗚)。

二、WebSocket是什么

WebSocket 這個關鍵詞,我在平時的工作和學習中已經聽過了很多次了,但是對于它的認知還是停留在淺顯的表面。所以很有必要重新系統的認識一下它!首先需要弄清楚的就是 WebSocket 是什么。

WebSocket 是一種網絡通信協議,和 HTTP 同處于應用層。它的出現解決了 HTTP 的一個缺陷:服務器只能被動發送數據給客戶端,不能進行主動推送。WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。

在WebSocket API中,瀏覽器和服務器只需要完成一次握手,兩者之間就可以建立持久性的連接,并進行雙向數據傳輸。這對于需要連續數據交換的服務,例如網絡游戲,實時交易系統等,WebSocket 尤其有用。

這個特點別看簡單,但是解決了很多復雜的業務難題,比如刷微博。我們都知道刷微博是一個沒有盡頭的事情,因為每當你刷完當前的東西,頁面 header 區域又出現“你的關注博主有n條新微博”的提示。而且即使你在刷微博的過程中沒有刷新頁面,這個未讀微博的提醒也會出現。這說明了微博服務器在沒有收到客戶端請求時,主動向客戶端推送了一些數據。

下面我們解放一下我們的大腦,做一個假設。如果 WebSocket 不存在的話,我們如果使用 HTTP 實現微博的這個需求呢?

如果使用 HTTP 實現這個需求,想要做到及時獲取到服務器上的新數據,無非就是輪詢。但是不管是普通輪詢還是變種的長輪詢(Long Polling),都加重了服務器資源的消耗。因為服務器需要在一定時間內持續地處理客戶端的 http 請求。

當數據頻繁的時候,這種方式會拖垮服務器,造成后端應用的崩潰,所以不適合作為解決方案。

這個時候再讓我們的目光回到 WebSokcet 的身上,它就可以很好解決這個問題。WebSocket 允許服務端主動向客戶端推送消息,并且沒有同源限制。

三、如何使用 WebSocket

上面介紹了 WebSocket 是什么,以及它的應用場景:服務器主動推送消息。那么下面需要介紹一下 WebSokcet 的使用。

要打開一個 WebSocket 連接,我們需要在 url 中使用特殊的協議 ws 創建 new WebSocket:

  1. let socket = new WebSocket("ws://javascript.info"); 

同樣也有一個加密的 wss:// 協議。類似于 WebSocket 中的 HTTPS。

一旦 socket 被建立,我們就應該監聽 socket 上的事件。一共有 4 個事件:

  • open — 連接已建立
  • message — 接收到數據
  • error — WebSocket 錯誤
  • close — 連接已關閉

……如果我們想發送一些東西,那么可以使用 socket.send(data),這是一個示例:

  1. let socket = new WebSocket("wss://javascript.info/article/websocket/demo/hello"); 
  2.  
  3. socket.onopen = function(e) { 
  4.   alert("[open] Connection established"); 
  5.   alert("Sending to server"); 
  6.   socket.send("My name is John"); 
  7. }; 
  8.  
  9. socket.onmessage = function(event) { 
  10.   alert(`[message] Data received from server: ${event.data}`); 
  11. }; 
  12.  
  13. socket.onclose = function(event) { 
  14.   if (event.wasClean) { 
  15.     alert(`[closeConnection closed cleanly, code=${event.code} reason=${event.reason}`); 
  16.   } else { 
  17.     // 例如服務器進程被殺死或網絡中斷 
  18.     // 在這種情況下,event.code 通常為 1006 
  19.     alert('[close] Connection died'); 
  20.   } 
  21. }; 
  22.  
  23. socket.onerror = function(error) { 
  24.   alert(`[error] ${error.message}`); 
  25. }; 

出于演示目的,在上面的示例中,運行著一個用 Node.js 寫的小型服務器 server.js(https://zh.javascript.info/article/websocket/demo/server.js)。它響應為 “Hello from server, John”,然后等待 5 秒,關閉連接。

所以你看到的事件順序為:open → message → close。

這就是 WebSocket,我們已經可以使用 WebSocket 通信了。很簡單,不是嗎?

四、前后臺通訊

1. 應用角色模型

當我們需要在前臺應用和后臺應用之間進行數據通訊的時候,我們首先需要知道它們兩個的角色是什么。

最開始我想當然認為一個是「服務端」,另一個是「客戶端」。那么如何確定哪個是服務端呢?另外如果多個應用需要保持數據同步呢?這些問題讓我需要重新定位它們的角色。

從更加通用的角度來思考,我們需要一個獨立的進程充當服務端的角色,其余的前端應用作為客戶端。這樣的話無論客戶端的數量多少,都可以通過這個服務端為中介來進行應用間的數據同步。架構圖如下:

從上圖我們可以知道,socket 進程需要在啟動其中一個客戶端應用時一起啟動。然后其余的客戶端應用都與這個 socket 進程建立連接,并進行數據的交換。

2. 新的問題:如何啟動一個 socket 進程

在知道了架構邏輯之后,新的問題出現了。我們從 socket 示例知道建立一個 socket 連接,需要一個 ws/wss 協議開頭的 url 字符串。這個字符串需要從哪里得到呢?

我們首先回歸到問題的本質,如何建立一個 socket 連接?

  1. let socket = new WebSocket("ws://javascript.info"); 

上面的這行代碼就是最簡單的建立 socket 連接的方式。但這行代碼背后存在了一個隱藏的角色:服務端。

那么我們需要怎么才能啟動一個 socket 服務,并且客戶端與這個后端服務建立連接呢?這個問題冒出來了之后,我第一時間想找找有沒有建好的輪子。果然已經有前輩封裝好了包:socket.io(服務端)和 socket.io.client(客戶端)。

3. 服務端代碼

  1. // ws/index.js 
  2. const server = require('http').createServer() 
  3. const io = require('socket.io')(server) 
  4.  
  5. // 綁定事件 
  6. io.on('connect', socket => { 
  7.   console.log('服務端建立連接成功!'
  8.   socket.on('disconnet', () => { 
  9.     console.log('服務端監測到已斷開連接'
  10.   }) 
  11.   socket.on('transportData', (data) => { 
  12.     console.log('服務端監測到數據傳輸', data) 
  13.     io.sockets.emit('updateData', data) 
  14.     console.log('服務端emit事件updateData'
  15.   }) 
  16. }) 
  17.  
  18. // 啟動服務器程序進行監聽 
  19. server.listen(8020, () => { 
  20.   console.log('==== socket server is running at 1234 port ===='
  21. }) 

以上就是服務端 socket 程序的簡單代碼,要注意的是這里我們使用的是 Socket.io。Socket.io 將 Websocket 和輪詢(Polling)機制以及其它的實時通信方式封裝成了通用的接口,并且在服務端實現了這些實時機制的相應代碼。也就是說,Websocket 僅僅是 Socket.io實現實時通信的一個子集。它很好的解決了不同瀏覽器的兼容性問題,我們可以將更多精力放在業務邏輯上。

這段代碼的核心就是監聽(on)和拋出(emit)事件。它 emit 出的事件會被連接的各個客戶端監聽到的,前提是每個客戶端都做了事件監聽。

4. 客戶端代碼

  1. // client1.vue 
  2. <script> 
  3. import io from 'socket.io-client' 
  4.    
  5. export default { 
  6.     ... 
  7.     mounted () { 
  8.         const socket = io('http://127.0.0.1:8020'
  9.      
  10.     socket.on('connect', () => { 
  11.       console.log('client1建立連接成功'
  12.       console.log('client1傳輸數據'
  13.       socket.emit('transportData', {name'xuhx'}) 
  14.     }) 
  15.     socket.on('updateData', (data) => { 
  16.       console.log('client1監聽到數據更新', data) 
  17.     }) 
  18.     } 
  19. </script> 

 

上面這段代碼是客戶端1的代碼,主要做的是與 socket 服務端建立連接,然后監聽和拋出相應的事件。

  1. // client2.vue 
  2. <script> 
  3. import io from 'socket.io-client' 
  4.    
  5. export default { 
  6.     ... 
  7.     mounted () { 
  8.         const socket = io('http://127.0.0.1:8020'
  9.      
  10.     socket.on('connect', () => { 
  11.       console.log('client2建立連接成功'
  12.     }) 
  13.     socket.on('updateData', (data) => { 
  14.       console.log('client2監聽到數據更新', data) 
  15.     }) 
  16.     } 
  17. </script> 

 

當 socket 進程拋出了 updateData 事件后,client1 與 client2 都可以監聽到了這個事件,并且拿到了傳遞的數據。

那么通過上面的數據傳輸圖,我們就可以知道客戶端可以通過 emit 自定義事件,經過 socket 中轉然后被其他客戶端監聽到事件,從而保持客戶端應用之間數據的同步。

五、其他通訊方式

沒有哪種解決方案是十全十美的,都是更合適某種業務場景。針對前端不同的業務場景,需要采用不同的解決方案來實現需求。那么除了 WebSocket 之外,還有哪些方案可以用于前端應用之間通訊呢?下面我結合實際開發工作列舉一下。

那么首先需要對業務場景進行分類:前端跨頁面之間通訊是否是同源頁面。這個分類方式很好理解,就是兩個通訊的頁面是不是屬于同一個前端項目。同源頁面的通訊有很多方式,我們主要解決非同源頁面之間的通信。

1. Cookie

如果應用 A 和應用 B 的根域名相同,只不過子級域名不同,例如:tieba.baidu.com 和 waimai.baidu.com。那么如何在這兩個應用頁面之間進行數據的傳輸呢?有些同學會想到 sessionStorage 和 LocalStorage,但是它們的存儲的基礎是同源的。應用 A 無法訪問到應用 B 下的 sessionStorage的。但是對應的 Cookie 就能滿足我們的需求,那是因為 Cookie 可以設置存儲的 Domain。如果將其 domain 設為根域名,那么應用 A 就可以訪問應用 B 下的 Cookie 數據。

Cookie 這種解決方案不適合存儲大量數據,因為每次請求都會攜帶 cookie,容易造成帶寬資源的浪費。它很合適某種狀態的傳遞,例如用戶在應用 A 中是否領取了會員卡,應用 B 通過 Cookie 讀取領取狀態進行對應業務邏輯的處理。

2. iframe + window.postMessage()

當應用 A 和應用 B 的根域名相同時,我們可以采用 Cookie 的方式。然而有時候,我們有兩個不同域名的產品線,也希望它們下面的所有頁面之間能無障礙地通信。那該怎么辦呢?

要實現該功能,可以使用一個用戶不可見的 iframe 作為“橋”。由于 iframe 與父頁面間可以通過指定origin來忽略同源限制,因此可以在頁面中嵌入一個 iframe (例如:http://sample.com/bridge.html),而這些 iframe 由于使用的是一個 url,因此屬于同源頁面。然后使用 window.postMessage() 進行外層應用和內嵌應用之間的通信。

3. Server Sent Events

Server-Sent Events 規范描述了一個內建的類 EventSource,它能保持與服務器的連接,并允許從中接收事件。與 WebSocket 類似,其連接是持久的。

但是兩者之間有幾個重要的區別:

WebSocket EventSource
雙向:客戶端和服務端都能交換消息 單向:僅服務端能發送消息
二進制和文本數據 僅文本數據
WebSocket 協議 常規 HTTP 協議

與 WebSocket 相比,EventSource 是與服務器通信的一種不那么強大的方式。

我們為什么要使用它?

主要原因:簡單。在很多應用中,WebSocket 有點大材小用。

我們需要從服務器接收一個數據流:可能是聊天消息或者市場價格等。這正是 EventSource 所擅長的。它還支持自動重新連接,而在 WebSocket 中這個功能需要我們手動實現。此外,它是一個普通的舊的 HTTP,不是一個新協議。

4. 微前端

微前端作為前端的一個前沿技術,我是聽說了很久但是一直沒有機會去使用。并且聽同事的介紹,現在微前端的使用還有不少坑。但是它確實是一個應用間通信、協作的探索方向之一。具體的使用和思路就需要大家自行探索了啊。

上面我列舉了3 個其他非同源頁面之間的通訊方式。實際上在我搜尋相關資料的時候,發現了同行梳理的很多方式。但我發現很難記住這么多的方式,其中一些方式甚至基本不可能使用,徒增記憶的負擔。所以我在這里僅列舉了主流好用的方式,一招鮮吃遍天~~

六、小結

兩個前端工程之間需要進行數據通訊,可以采取 WebSocket 的方式。項目單獨啟動一個進程,作為 socket 服務端。需要數據通訊的前端應用在頁面中與 socket 進程建立連接,通過 emit 自定義事件和監聽相應的事件來實現兩個不同應用之間的數據同步。本篇文章寫的其實是 WebSocket 的基本使用,結合到具體的業務開發中總結了一下。希望能夠對遇到相關需求的朋友有所幫助。

許浩星,微醫前端技術部前端工程師。一個認為人生的樂趣一半在靜,一半在動的有志青年!

 

責任編輯:武曉燕 來源: 微醫大前端技術
相關推薦

2015-06-30 10:48:41

iOSAPPwarchkit

2010-09-02 19:55:35

斐訊數據通信

2009-01-10 23:47:27

軟考數據通信信道

2022-03-15 20:41:36

全無線低碳智能樓宇網

2022-04-22 21:22:18

華為

2021-10-15 12:09:27

華為

2017-01-23 13:34:44

2020-08-18 21:55:31

華為

2010-05-20 15:22:02

LOGOIP數據通信斐訊通信

2010-12-21 18:25:58

2012-02-27 17:39:58

新數通

2009-11-19 14:19:45

核心路由器

2011-11-14 16:19:01

2022-11-08 13:47:37

設備
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 一级毛片免费 | 日韩在线视频一区 | 99久久国产综合精品麻豆 | 欧美性吧 | 视频1区 | 国产精品日韩欧美一区二区三区 | 久久精品亚洲 | 日韩欧美一区二区三区 | 欧美美女二区 | 欧美日本免费 | 99精品电影 | 亚洲精品粉嫩美女一区 | 精品国产一区二区三区久久久久久 | 久久精品久久精品久久精品 | 日韩av.com| 伊人热久久| 伊人网91 | 免费人成在线观看网站 | 成人在线观看欧美 | 亚洲电影中文字幕 | 国产精品中文字幕在线 | 一区二区三区国产好的精 | 亚洲福利网 | 国产高清在线观看 | 婷婷丁香在线视频 | 日本不卡免费新一二三区 | 亚洲精品日韩一区二区电影 | 99久久免费精品国产免费高清 | 中文字幕1区2区3区 日韩在线视频免费观看 | 一区二区三区视频 | 黄色av免费网站 | 国产1区| 成人免费一区二区 | 99久久婷婷 | 99亚洲视频| jizz视频| 精品综合 | 亚洲精品乱码久久久久久9色 | 欧美一级黄色免费看 | 99久热在线精品视频观看 | 成人在线视频网站 |