gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区

站長資訊網
最全最豐富的資訊網站

Node和React中如何進行實時通信?

Node和React中如何進行實時通信?

教程推薦:node js教程、React教程、WebSocket教程

Web 為了支持客戶端和服務器之間的全雙工(或雙向)通信已經走過了很長的路。這是 WebSocket 協議的主要目的:通過單個 TCP 套接字連接在客戶端和服務器之間提供持久的實時通信。

WebSocket 協議只有兩個議程:1)打開握手,2)幫助數據傳輸。一旦服務器和客戶端握手成功,他們就可以隨意地以較少的開銷相互發送數據。

WebSocket 通信使用WS(端口80)或WSS(端口443)協議在單個 TCP 套接字上進行。根據 Can I Use,撰寫本文時除了 Opera Mini 之外幾乎所有的瀏覽器支持 WebSockets 。

現狀

從歷史上看,創建需要實時數據通訊(如游戲或聊天應用程序)的 Web 應用需要濫用 HTTP 協議來建立雙向數據傳輸。盡管有許多種方法用于實現實時功能,但沒有一種方法與 WebSockets 一樣高效。 HTTP 輪詢、HTTP流、Comet、SSE —— 它們都有自己的缺點。

HTTP 輪詢

解決問題的第一個嘗試是定期輪詢服務器。 HTTP 長輪詢生命周期如下:

  1. 客戶端發出請求并一直等待響應。
  2. 服務器推遲響應,直到發生更改、更新或超時。請求保持“掛起”,直到服務器有東西返回客戶端。
  3. 當服務器端有一些更改或更新時,它會將響應發送回客戶端。
  4. 客戶端發送新的長輪詢請求以偵聽下一組更改。

長輪詢中存在很多漏洞 —— 標頭開銷、延遲、超時、緩存等等。

HTTP 流式傳輸

這種機制減少了網絡延遲的痛苦,因為初始請求無限期地保持打開狀態。即使在服務器推送數據之后,請求也永遠不會終止。 HTTP 流中的前三步生命周期方法與 HTTP 輪詢是相同的。

但是,當響應被發送回客戶端時,請求永遠不會終止,服務器保持連接打開狀態,并在發生更改時發送新的更新。

服務器發送事件(SSE)

使用 SSE,服務器將數據推送到客戶端。聊天或游戲應用不能完全依賴 SSE。 SSE 的完美用例是類似 Facebook 的新聞 Feed:每當有新帖發布時,服務器會將它們推送到時間線。 SSE 通過傳統 HTTP 發送,并且對打開的連接數有限制。

這些方法不僅效率低下,維護它們的代碼也使開發人員感到厭倦。

WebSocket

WebSockets 旨在取代現有的雙向通信技術。當涉及全雙工實時通信時,上述現有方法既不可靠也不高效。

WebSockets 類似于 SSE,但在將消息從客戶端傳回服務器方面也很優秀。由于數據是通過單個 TCP 套接字連接提供的,因此連接限制不再是問題。


實戰教程

正如介紹中所提到的,WebSocket 協議只有兩個議程。讓我們看看 WebSockets 如何實現這些議程。為此我將分析一個 Node.js 服務器并將其連接到使用 React.js 構建的客戶端上。

議程1:WebSocket在服務器和客戶端之間建立握手

在服務器級別創建握手

我們可以用單個端口來分別提供 HTTP 服務和 WebSocket 服務。下面的代碼顯示了一個簡單的 HTTP 服務器的創建過程。一旦創建,我們會將 WebSocket 服務器綁定到 HTTP 端口:

const webSocketsServerPort = 8000; const webSocketServer = require('websocket').server; const http = require('http'); // Spinning the http server and the websocket server. const server = http.createServer(); server.listen(webSocketsServerPort); const wsServer = new webSocketServer({   httpServer: server });

創建 WebSocket 服務器后,我們需要在接收來自客戶端的請求時接受握手。我將所有連接的客戶端作為對象保存在代碼中,并在收請從瀏覽器發來的求時使用唯一的用戶ID。

// I'm maintaining all active connections in this object const clients = {};  // This code generates unique userid for everyuser. const getUniqueID = () => {   const s4 = () => Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);   return s4() + s4() + '-' + s4(); };  wsServer.on('request', function(request) {   var userID = getUniqueID();   console.log((new Date()) + ' Recieved a new connection from origin ' + request.origin + '.');   // You can rewrite this part of the code to accept only the requests from allowed origin   const connection = request.accept(null, request.origin);   clients[userID] = connection;   console.log('connected: ' + userID + ' in ' + Object.getOwnPropertyNames(clients)) });

那么,當接受連接時會發生什么?

在發送常規 HTTP 請求以建立連接時,在請求頭中,客戶端發送 *Sec-WebSocket-Key*。服務器對此值進行編碼和散列,并添加預定義的 GUID。它回應了服務器發送的握手中 *Sec-WebSocket-Accept*中生成的值。

一旦請求在服務器中被接受(在必要驗證之后),就完成了握手,其狀態代碼為 101。如果在瀏覽器中看到除狀態碼 101 之外的任何內容,則意味著 WebSocket 升級失敗,并且將遵循正常的 HTTP 語義。

*Sec-WebSocket-Accept* 頭字段指示服務器是否愿意接受連接。此外如果響應缺少 *Upgrade* 頭字段,或者 *Upgrade* 不等于 websocket,則表示 WebSocket 連接失敗。

成功的服務器握手如下所示:

HTTP GET ws://127.0.0.1:8000/ 101 Switching Protocols Connection: Upgrade Sec-WebSocket-Accept: Nn/XHq0wK1oO5RTtriEWwR4F7Zw= Upgrade: websocket

在客戶端級別創建握手

在客戶端,我使用與服務器中的相同 WebSocket 包來建立與服務器的連接(Web IDL 中的 WebSocket API 正在由W3C 進行標準化)。一旦服務器接受請求,我們將會在瀏覽器控制臺上看到 WebSocket Client Connected

這是創建與服務器的連接的初始腳手架:

import React, { Component } from 'react'; import { w3cwebsocket as W3CWebSocket } from "websocket";  const client = new W3CWebSocket('ws://127.0.0.1:8000');  class App extends Component {   componentWillMount() {     client.onopen = () => {       console.log('WebSocket Client Connected');     };     client.onmessage = (message) => {       console.log(message);     };   }      render() {     return (       <div>         Practical Intro To WebSockets.       </div>     );   } }  export default App;

客戶端發送以下標頭來建立握手:

HTTP GET ws://127.0.0.1:8000/ 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: vISxbQhM64Vzcr/CD7WHnw== Origin: http://localhost:3000 Sec-WebSocket-Version: 13

現在客戶端和服務器通過相互握手進行了連接,WebSocket 連接可以在接收消息時傳輸消息,從而實現 WebSocket 協議的第二個議程。

議程2:實時信息傳輸

Node和React中如何進行實時通信?

我將編寫一個基本的實時文檔編輯器,用戶可以將它們連接在一起并編輯文檔。我跟蹤了兩個事件:

  1. 用戶活動:每次用戶加入或離開時,我都會將消息廣播給所有連接其他的客戶端。
  2. 內容更改:每次修改編輯器中的內容時,都會向所有連接的其他客戶端廣播。

該協議允許我們用二進制數據或 UTF-8 發送和接收消息(注意:傳輸和轉換 UTF-8 的開銷較小)。

只要我們對套接字事件onopenoncloseonmessage有了充分的了解,理解和實現 WebSockets 就非常簡單。客戶端和服務器端的術語相同。

在客戶端發送和接收消息

在客戶端,當新用戶加入或內容更改時,我們用 client.send 向服務器發消息,以將新信息提供給服務器。

/* When a user joins, I notify the server that a new user has joined to edit the document. */ logInUser = () => {   const username = this.username.value;   if (username.trim()) {     const data = {       username     };     this.setState({       ...data     }, () => {       client.send(JSON.stringify({         ...data,         type: "userevent"       }));     });   } }  /* When content changes, we send the current content of the editor to the server. */ onEditorStateChange = (text) => {  client.send(JSON.stringify({    type: "contentchange",    username: this.state.username,    content: text  })); };

我們跟蹤的事件是:用戶加入和內容更改。

從服務器接收消息非常簡單:

componentWillMount() {   client.onopen = () => {    console.log('WebSocket Client Connected');   };   client.onmessage = (message) => {     const dataFromServer = JSON.parse(message.data);     const stateToChange = {};     if (dataFromServer.type === "userevent") {       stateToChange.currentUsers = Object.values(dataFromServer.data.users);     } else if (dataFromServer.type === "contentchange") {       stateToChange.text = dataFromServer.data.editorContent || contentDefaultMessage;     }     stateToChange.userActivity = dataFromServer.data.userActivity;     this.setState({       ...stateToChange     });   }; }

在服務器端發送和偵聽消息

在服務器中,我們只需捕獲傳入的消息并將其廣播到連接到 WebSocket 的所有客戶端。這是臭名昭著的 Socket.IO 和 WebSocket 之間的差異之一:當我們使用 WebSockets 時,我們需要手動將消息發送給所有客戶端。 Socket.IO 是一個成熟的庫,所以它自己來處理。

const sendMessage = (json) => {   // We are sending the current data to all connected clients   Object.keys(clients).map((client) => {     clients[client].sendUTF(json);   }); }  connection.on('message', function(message) {     if (message.type === 'utf8') {       const dataFromClient = JSON.parse(message.utf8Data);       const json = { type: dataFromClient.type };       if (dataFromClient.type === typesDef.USER_EVENT) {         users[userID] = dataFromClient;         userActivity.push(`${dataFromClient.username} joined to edit the document`);         json.data = { users, userActivity };       } else if (dataFromClient.type === typesDef.CONTENT_CHANGE) {         editorContent = dataFromClient.content;         json.data = { editorContent, userActivity };       }       sendMessage(JSON.stringify(json));     }   });

將消息廣播到所有連接的客戶端。

Node和React中如何進行實時通信?

瀏覽器關閉后會發生什么?

在這種情況下,WebSocket調用 close 事件,它允許我們編寫終止當前用戶連接的邏輯。在我的代碼中,當用戶離開文檔時,會向其余用戶廣播消息:

connection.on('close', function(connection) {     console.log((new Date()) + " Peer " + userID + " disconnected.");     const json = { type: typesDef.USER_EVENT };     userActivity.push(`${users[userID].username} left the document`);     json.data = { users, userActivity };     delete clients[userID];     delete users[userID];     sendMessage(JSON.stringify(json));   });

該應用程序的源代碼位于GitHub上的 repo 中。

結論

WebSockets 是在應用中實現實時功能的最有趣和最方便的方法之一。它為我們提供了能夠充分利用全雙工通信的靈活性。我強烈建議在嘗試使用 Socket.IO 和其他可用庫之前先試試 WebSockets。

編碼快樂!

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区
少妇无码av无码专区在线观看| 中文字幕国内自拍| 手机免费看av网站| avav在线看| www激情五月| 99亚洲精品视频| 国产成人黄色网址| 日韩一区二区三区不卡视频| 无罩大乳的熟妇正在播放| 国产va亚洲va在线va| 国产成人一二三区| 青春草国产视频| 欧美二区在线视频| 91淫黄看大片| 超碰在线人人爱| av动漫免费看| 黄色一级在线视频| avav在线看| 在线能看的av网站| 午夜影院免费版| 午夜在线观看av| 久久久久久久久久久久91| 成人免费观看cn| 中文精品无码中文字幕无码专区| 手机在线国产视频| 日韩一级片播放| 亚洲色精品三区二区一区| 国产欧美日韩小视频| 亚洲精品蜜桃久久久久久| 国产女主播av| a级免费在线观看| 欧美一级欧美一级| 亚洲高清av一区二区三区| 午夜xxxxx| 国产精品自在自线| 麻豆md0077饥渴少妇| 欧美国产视频一区| 欧美二区在线视频| 国产精品视频一二三四区| 法国空姐在线观看免费| 男女h黄动漫啪啪无遮挡软件| 麻豆一区二区三区在线观看| 伊人网在线免费| 国产男女在线观看| 另类小说第一页| 中文字幕第50页| 成人免费毛片在线观看| 亚洲天堂2018av| 97超碰在线视| 青青草原国产在线视频| 日本精品福利视频| 黑人粗进入欧美aaaaa| 国产一级免费大片| 成人在线免费观看av| 国产精品久久久久久久99| 日韩av在线播放不卡| 男女污污的视频| 91专区在线观看| 无码毛片aaa在线| 黄色成人免费看| 免费欧美一级视频| 国产911在线观看| 中文字幕久久av| 成人小视频在线观看免费| 57pao国产成永久免费视频| 99免费视频观看| 中文字幕无码精品亚洲35| 国产手机视频在线观看| 日日噜噜夜夜狠狠| 国产一区视频免费观看| 久久久噜噜噜www成人网| 国产在线视频在线| 日韩一二区视频| 久久婷婷中文字幕| 亚洲制服中文字幕| 亚洲视频在线不卡| 亚洲在线观看网站| 永久免费在线看片视频| 黄色a级三级三级三级| 中文字幕第38页| 一区二区三区网址| 日韩成人精品视频在线观看| 在线观看国产福利| 可以免费看的黄色网址| 日韩精品一区二区免费| 少妇人妻无码专区视频| 久久国产精品免费观看| 黄色三级视频在线播放| 欧美日韩午夜爽爽| 乱熟女高潮一区二区在线| 日韩一级性生活片| 国产情侣av自拍| 亚洲第一天堂久久| 手机看片日韩国产| 欧美视频在线播放一区| 日本成人中文字幕在线| 熟女熟妇伦久久影院毛片一区二区| 中文字幕55页| 成人在线观看你懂的| 91福利国产成人精品播放| 欧美国产日韩另类 | 特级西西444www| 六月婷婷激情综合| 国产偷人视频免费| 亚洲一区 在线播放| 欧美一级特黄a| 春日野结衣av| 免费的一级黄色片| 日韩无套无码精品| 日本a在线天堂| 色噜噜狠狠一区二区三区狼国成人| 日本手机在线视频| 日本成人性视频| 超碰在线97免费| 久久精品免费一区二区| 国产精品无码乱伦| 爱情岛论坛亚洲首页入口章节| 青青在线视频免费观看| 最新av在线免费观看| 亚洲精品永久视频| 天堂在线资源视频| 日本美女高潮视频| 91av在线免费播放| 中国丰满人妻videoshd| 欧美图片激情小说| 99久久国产综合精品五月天喷水| 国产又粗又长又爽又黄的视频| 欧美伦理片在线观看| 天天想你在线观看完整版电影免费| 狠狠躁狠狠躁视频专区| 99视频在线视频| 成人日韩在线视频| 爱豆国产剧免费观看大全剧苏畅| 中文字幕在线观看日| av在线网址导航| 91欧美一区二区三区| 不卡中文字幕在线| 成人小视频在线观看免费| 一卡二卡三卡视频| 日韩一级在线免费观看| 岛国av在线免费| 影音先锋男人的网站| 黄色一级视频在线播放| 日韩精品一区二区三区色欲av| 亚洲 欧美 日韩系列| 91视频福利网| 日韩精品一区二区免费| 亚洲欧美激情网| 国产情侣第一页| 中文字幕第38页| 九九九九免费视频| 五月六月丁香婷婷| 久激情内射婷内射蜜桃| 久久久久国产一区| 久操手机在线视频| 超碰在线97免费| www国产精品内射老熟女| 欧美 日本 亚洲| 色偷偷中文字幕| 97xxxxx| 国产真人无码作爱视频免费| 爱爱爱视频网站| 日本888xxxx| 亚洲熟妇无码一区二区三区导航| 免费黄色一级网站| 男人天堂1024| 成 年 人 黄 色 大 片大 全| 日本中文字幕影院| 538在线视频观看| 大桥未久一区二区| 欧美日韩视频免费在线观看| 中文字幕在线观看第三页| 日本www在线视频| 亚洲国产一二三精品无码| 中文字幕久久av| 国产又粗又硬又长| 国产av第一区| 日韩精品久久一区二区| 视频一区二区视频| 91看片淫黄大片91| 樱花草www在线| 欧美日韩视频免费| 欧美黑人在线观看| 日本午夜激情视频| 成年人免费在线播放| 免费在线a视频| 亚洲欧美自偷自拍另类| 成人免费在线观看视频网站| 欧洲熟妇精品视频| 尤物网站在线看| 久久综合久久网| 日韩精品一区二区三区久久| 成人羞羞国产免费网站| 十八禁视频网站在线观看| 亚洲一级片av| 男女日批视频在线观看| 欧美一级特黄a| 欧美成人免费在线观看视频| 成人久久久久久久久| 在线观看视频黄色|