3分鐘使用 WebSocket 搭建屬于自己的聊天室(WebSocket 原理、應用解析)

文章目錄

  • WebSocket 的由來
  • WebSocket 是什么
    • WebSocket 優缺點
      • 優點
      • 缺點
    • WebSocket 適用場景
    • 主流瀏覽器對 WebSocket 的兼容性
    • WebSocket 通信過程以及原理
      • 建立連接
        • 具體過程
        • 示例
          • Sec-WebSocket-Key
          • Sec-WebSocket-Extensions
      • 數據通信
        • 數據幀
          • 幀頭(Frame Header)
          • 掩碼(Masking)
          • 負載數據(Payload Data)
        • 來自 MDN 的一個小例子
      • 維持連接
      • 關閉連接
  • 使用 WebSocket 實現一個簡易聊天室
    • 前端源碼
    • 后端源碼 Java
  • 總結
  • 參考
  • 個人簡介

WebSocket 的由來

  • 在 WebSocket 出現之前,我們想實現實時通信、變更推送、服務端消息推送功能,我們一般的方案是使用 Ajax 短輪詢、長輪詢兩種方式:
  • 比如我們想實現一個服務端數據變更時,立即通知客戶端功能,沒有 WebSocket 之前我們可能會采用以下兩種方案:短輪詢或長輪詢

短輪詢、長輪詢(來源:即時通訊網)

  • 上面兩種方案都有比較明顯的缺點:
1、HTTP 協議包含的較長的請求頭,有效數據只占很少一部分,浪費帶寬
2、短輪詢頻繁輪詢對服務器壓力較大,即使使用長輪詢方案,客戶端較多時仍會對客戶端造成不小壓力
  • 在這種情況下,HTML5 定義了 WebSocket 協議,能更好的節省服務器資源和帶寬,并且能夠更實時地進行通訊。

WebSocket 是什么

  • WebSocket 是一種網絡傳輸協議,可在單個 TCP 連接上進行全雙工通信,位于 OSI 模型的應用層。
  • WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。客戶端和服務器只需要完成一次握手,兩者之間就可以創建持久性的連接,并進行雙向數據傳輸。

短輪詢和WebSocket的區別(來源:即時通訊網)

WebSocket 優缺點

優點

  • 實時性: WebSocket 提供了雙向通信,服務器可以主動向客戶端推送數據,實現實時性非常高,適用于實時聊天、在線協作等應用。
  • 減少網絡延遲: 與輪詢和長輪詢相比,WebSocket 可以顯著減少網絡延遲,因為不需要在每個請求之間建立和關閉連接。
  • 較小的數據傳輸開銷: WebSocket 的數據幀相比于 HTTP 請求報文較小,減少了在每個請求中傳輸的開銷,特別適用于需要頻繁通信的應用。
  • 較低的服務器資源占用: 由于 WebSocket 的長連接特性,服務器可以處理更多的并發連接,相較于短連接有更低的資源占用。
  • 跨域通信: 與一些其他跨域通信方法相比,WebSocket 更容易實現跨域通信。

缺點

  • 連接狀態保持: 長時間保持連接可能會導致服務器和客戶端都需要維護連接狀態,可能增加一些負擔。
  • 不適用于所有場景: 對于一些請求-響應模式較為簡單的場景,WebSocket 的實時特性可能并不是必要的,使用 HTTP 請求可能更為合適。
  • 復雜性: 與傳統的 HTTP 請求相比,WebSocket 的實現和管理可能稍顯復雜,尤其是在處理連接狀態、異常等方面。

WebSocket 適用場景

  • 實時聊天應用: WebSocket 是實現實時聊天室、即時通訊應用的理想選擇,因為它能夠提供低延遲和高實時性。
  • 在線協作和協同編輯: 對于需要多用戶協同工作的應用,如協同編輯文檔或繪圖,WebSocket 的實時性使得用戶能夠看到其他用戶的操作。
  • 實時數據展示: 對于需要實時展示數據變化的應用,例如股票行情、實時監控系統等,WebSocket 提供了一種高效的通信方式。
  • 在線游戲: 在線游戲通常需要快速、實時的通信,WebSocket 能夠提供低延遲和高并發的通信能力。
  • 推送服務: 用于實現消息推送服務,向客戶端主動推送更新或通知。

主流瀏覽器對 WebSocket 的兼容性

主流瀏覽器對 WebSocket 的兼容性

  • 由上圖可知:目前主流的 Web 瀏覽器都支持 WebSocket,因此我們可以在大多數項目中放心地使用它。

WebSocket 通信過程以及原理

建立連接

  • WebSocket 協議屬于應用層協議,依賴傳輸層的 TCP 協議。它通過 HTTP/1.1 協議的 101 狀態碼進行握手建立連接。
具體過程
  • 客戶端發送一個 HTTP GET 請求到服務器,請求的路徑是 WebSocket 的路徑(類似 ws://example.com/socket)。請求中包含一些特殊的頭字段,如 Upgrade: websocket 和 Connection: Upgrade,以表明客戶端希望升級連接為 WebSocket。
  • 服務器收到這個請求后,會返回一個 HTTP 101 狀態碼(協議切換協議)。同樣在響應頭中包含 Upgrade: websocket 和 Connection: Upgrade,以及一些其他的 WebSocket 特定的頭字段,例如 Sec-WebSocket-Accept,用于驗證握手的合法性。
  • 客戶端和服務器之間的連接從普通的 HTTP 連接升級為 WebSocket 連接。之后,客戶端和服務器之間的通信就變成了 WebSocket 幀的傳輸,而不再是普通的 HTTP 請求和響應。
示例
// 客戶端請求
GET ws://localhost:8888/ HTTP/1.1
Host: localhost:8888
Connection: Upgrade
Upgrade: websocket
Origin: http://localhost:63342
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,ja;q=0.8,en;q=0.7
Sec-WebSocket-Key: b7wpWuB9MCzOeQZg2O/yPg==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits// 服務端響應
HTTP/1.1 101 Web Socket Protocol Handshake
Connection: Upgrade
Date: Wed, 22 Nov 2023 08:15:00 GMT
Sec-WebSocket-Accept: Q4TEk+qOgJsKy7gedijA5AuUVIw=
Server: TooTallNate Java-WebSocket
Upgrade: websocket
Sec-WebSocket-Key
  • 與服務端響應頭部的 Sec-WebSocket-Accept 是配套的,提供基本的防護,比如惡意的連接,或者無意的連接;這里的“配套”指的是:Sec-WebSocket-Accept 是根據請求頭部的 Sec-WebSocket-Key 計算而來,計算過程大致為基于 SHA1 算法得到摘要并轉成 base64 字符串。
Sec-WebSocket-Extensions
  • 用于協商本次連接要使用的 WebSocket 擴展。

數據通信

  • WebSocket 的每條消息可能會被切分成多個數據幀(最小單位)。發送端會將消息切割成多個幀發送給接收端,接收端接收消息幀并將關聯的幀重新組裝成完整的消息。
數據幀
      0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-------+-+-------------+-------------------------------+|F|R|R|R| opcode|M| Payload len |    Extended payload length    ||I|S|S|S|  (4)  |A|     (7)     |             (16/64)           ||N|V|V|V|       |S|             |   (if payload len==126/127)   || |1|2|3|       |K|             |                               |+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +|     Extended payload length continued, if payload len == 127  |+ - - - - - - - - - - - - - - - +-------------------------------+|                               |Masking-key, if MASK set to 1  |+-------------------------------+-------------------------------+| Masking-key (continued)       |          Payload Data         |+-------------------------------- - - - - - - - - - - - - - - - +:                     Payload Data continued ...                :+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +|                     Payload Data continued ...                |+---------------------------------------------------------------+
幀頭(Frame Header)
  • FIN(1比特): 表示這是消息的最后一個幀。如果消息分成多個幀,FIN 位在最后一個幀上設置為 1。
  • RSV1、RSV2、RSV3(各1比特): 保留位,用于將來的擴展。
  • Opcode(4比特): 指定幀的類型,如文本幀、二進制幀、連接關閉等。
WebSocket 定義了幾種幀類型,其中最常見的是文本幀(Opcode 為 0x1)和二進制幀(Opcode 為 0x2)。其他幀類型包括連接關閉幀、Ping 幀、Pong 幀等。
  • Mask(1比特): 指示是否使用掩碼對負載進行掩碼操作。
  • Payload Length: 指定數據的長度。如果小于 126 字節,直接表示數據的長度。如果等于 126 字節,后面跟著 16 比特的無符號整數表示數據的長度。如果等于 127 字節,后面跟著 64 比特的無符號整數表示數據的長度。
掩碼(Masking)
  • 如果 Mask 位被設置為 1,則幀頭后面的 4 字節即為掩碼,用于對負載數據進行簡單的異或操作,以提高安全性。
負載數據(Payload Data)
  • 實際要傳輸的數據,可以是文本、二進制數據等
來自 MDN 的一個小例子
Client: FIN=1, opcode=0x1, msg="hello"
Server: (process complete message immediately) Hi.Client: FIN=0, opcode=0x1, msg="and a"
Server: (listening, newmessage containing text started)Client: FIN=0, opcode=0x0, msg="happy new"
Server: (listening, payload concatenated to previous message)Client: FIN=1, opcode=0x0, msg="year!"
Server: (process complete message) Happy new year to you too!

維持連接

  • 當建立連接后,連接可能因為網絡等原因斷開,我們可以使用心跳的方式定時檢測連接狀態。若連接斷開,我們可以告警或者重新建立連接。

關閉連接

  • WebSocket 是全雙工通信,當客戶端發送關閉請求時,服務端不一定立即響應,而是等服務端也同意關閉時再進行異步響應。
  • 下面是一個客戶端關閉的例子:
Client: FIN=1, opcode=0x8, msg="1000"
Server: FIN=1, opcode=0x8, msg="1000"

使用 WebSocket 實現一個簡易聊天室

  • 下面是一個簡易聊天室小案例,任何人打開下面的網頁都可以加入我們聊天室進行聊天,然后小紅和小明加入了聊天:

簡易聊天室

前端源碼

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>WebSocket Chat</title>
</head>
<body>
<div id="chat"></div>
<input type="text" id="messageInput" placeholder="Type your message">
<button onclick="sendMessage()">Send</button><script>const socket = new WebSocket('ws://localhost:8888');socket.onopen = (event) => {console.log('WebSocket connection opened:', event);};socket.onmessage = (event) => {const messageDiv = document.getElementById('chat');const messageParagraph = document.createElement('p');messageParagraph.textContent = event.data;messageDiv.appendChild(messageParagraph);};socket.onclose = (event) => {console.log('WebSocket connection closed:', event);};function sendMessage() {const messageInput = document.getElementById('messageInput');const message = messageInput.value;socket.send(message);messageInput.value = '';}
</script>
</body>
</html>

后端源碼 Java

package chat;import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;import java.net.InetSocketAddress;public class ChatServer extends WebSocketServer {public ChatServer(int port) {super(new InetSocketAddress(port));}@Overridepublic void onOpen(WebSocket conn, ClientHandshake handshake) {System.out.println("New connection from: " + conn.getRemoteSocketAddress().getAddress().getHostAddress());}@Overridepublic void onClose(WebSocket conn, int code, String reason, boolean remote) {System.out.println("Closed connection to: " + conn.getRemoteSocketAddress().getAddress().getHostAddress());}@Overridepublic void onMessage(WebSocket conn, String message) {System.out.println("Received message: " + message);// Broadcast the message to all connected clientsbroadcast(message);}@Overridepublic void onError(WebSocket conn, Exception ex) {System.err.println("Error on connection: " + ex.getMessage());}@Overridepublic void onStart() {}public static void main(String[] args) {int port = 8888;ChatServer server = new ChatServer(port);server.start();System.out.println("WebSocket Server started on port: " + port);}
}

總結

  • WebSocket 是一種在客戶端和服務器之間建立實時雙向通信的協議。具備全雙工、低延遲等優點,適用于實時聊天、多人協助、實時數據展示等場景。

參考

  • WebSocket:概念、原理

個人簡介

👋 你好,我是 Lorin 洛林,一位 Java 后端技術開發者!座右銘:Technology has the power to make the world a better place.

🚀 我對技術的熱情是我不斷學習和分享的動力。我的博客是一個關于Java生態系統、后端開發和最新技術趨勢的地方。

🧠 作為一個 Java 后端技術愛好者,我不僅熱衷于探索語言的新特性和技術的深度,還熱衷于分享我的見解和最佳實踐。我相信知識的分享和社區合作可以幫助我們共同成長。

💡 在我的博客上,你將找到關于Java核心概念、JVM 底層技術、常用框架如Spring和Mybatis 、MySQL等數據庫管理、RabbitMQ、Rocketmq等消息中間件、性能優化等內容的深入文章。我也將分享一些編程技巧和解決問題的方法,以幫助你更好地掌握Java編程。

🌐 我鼓勵互動和建立社區,因此請留下你的問題、建議或主題請求,讓我知道你感興趣的內容。此外,我將分享最新的互聯網和技術資訊,以確保你與技術世界的最新發展保持聯系。我期待與你一起在技術之路上前進,一起探討技術世界的無限可能性。

📖 保持關注我的博客,讓我們共同追求技術卓越。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/163538.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/163538.shtml
英文地址,請注明出處:http://en.pswp.cn/news/163538.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

組合數學學習

指數生成函數可以與排列結合在一起&#xff0c;而冪級數和 組合結合在一起 如果要進行計算的值不是一個具體的值&#xff0c;那么就要考慮生成函數

Windows如何使用key登錄Linux服務器

場景&#xff1a;因為需要回收root管理員權限&#xff0c;禁止root用戶遠程登錄&#xff0c;辦公環境只允許普通用戶遠程登錄&#xff0c;且不允許使用密碼登錄。 一、生成與配置ssh-key 1.使用root管理員權限登錄到目標系統。 2.創建一個新的普通用戶&#xff0c;和設置密碼用…

Java,File類與IO流,File類與IO流的概述

File的概述&#xff1a; File定義在java.io包下。 一個File對象代表硬盤或網絡中可能存在的一個文件或者文件目錄&#xff08;俗稱文件夾&#xff09;&#xff0c;與平臺無關。 File能新建、刪除、重命名文件和目錄&#xff0c;但File不能訪問文件內容本身。如果需要訪問文件…

用uniapp在微信小程序實現畫板(電子簽名)功能

目錄 一、效果展示 二、插件推薦與引入 三、代碼具體應用 四、h5端將base64轉換為url 一、效果展示 二、插件推薦與引入 手寫板、簽字板&#xff1b;<zwp-draw-pad /> - DCloud 插件市場 這個在微信小程序引入時內容簡單&#xff0c;且涉及的方法很多&#xff0c;…

【C/C++】排序算法代碼實現

這里&#xff0c;匯總了常見的排序算法具體代碼實現。使用C語言編寫。 排序算法實現 插入排序冒泡排序選擇排序快速排序希爾排序歸并排序 插入排序 #include <stdio.h> #include <stdlib.h>void InsertSort(int arr[],int n){int i,j,temp;for(i 1;i < n;i){ …

Pinia狀態持久化——插件pinia-plugin-persistedstate

pinia-plugin-persistedstate 旨在通過一致的 API 為 Pinia Store 提供持久化存儲。如果希望保存一個完整的 Store&#xff0c;或者需要細粒化配置 storage 和序列化的方式&#xff0c;該插件都提供了相應的功能&#xff0c;并且可以在想要持久化的 Store 上使用相同的配置。 …

Python 異常的傳遞性

實例 這里就簡單用2個function來演示一下異常的傳遞性 func1 這里num 1/0明顯是一個ZeroDivisionError錯誤&#xff0c;作為演示 def func1():print("fun1 開始執行")num 1 / 0print("func1 結束執行") func2 def func2():print("func2 開始執…

tomcat國密ssl測試

文章目錄 程序包準備部署配置訪問測試 程序包準備 下載 tomcat8.5 https://www.gmssl.cn/gmssl/index.jsp 下載 tomcat 國密組件及證書 本次測試所有的程序文件均已打包&#xff0c;可以直接 點擊下載 部署配置 自行完成 完成centos 的jdk配置。 部署tomcat,將 gmssl4t.jar…

數字孿生農村供水工程平臺:為鄉村振興注入新活力

隨著科技的不斷進步&#xff0c;數字孿生技術逐漸成為各行業創新發展的重要驅動力。在水利領域&#xff0c;數字孿生農村供水平臺以其獨特的優勢&#xff0c;為農村供水系統帶來了革命性的變革。本文將為您詳細介紹數字孿生農村供水平臺的核心特點及優勢&#xff0c;帶您領略智…

深度學習常見激活函數:ReLU,sigmoid,Tanh,softmax,Leaky ReLU,PReLU,ELU整理集合,應用場景選擇

文章目錄 1、ReLU 函數&#xff08;隱藏層中是一個常用的默認選擇&#xff09;1.1 優點1.2 缺點 2、sigmoid 函數2.1 優點2.2 缺點 3、Tanh 函數3.1 優點3.2 缺點 4、softmax 函數&#xff08;多分類任務最后一層都會使用&#xff09;5、Leaky ReLU 函數5.1 優點5.2 缺點 6、PR…

mongo DB -- aggregate分組查詢后字段展示

一、分組查詢 在mongoDB中可以使用aggregate中的$group操作對集合中的文檔進行分組,但是查詢后的數據不顯示其他字段,只顯示分組字段 aggregate進行分組示例 db.collection.aggregate([{$group: {_id: "$field"}},]) 查詢后顯示 展開只顯示兩個字段 二、顯示所有字段…

APM工具skywalking部署

一 整體架構 整個架構&#xff0c;分成上、下、左、右四部分&#xff1a; 上部分 Agent &#xff1a;負責從應用中&#xff0c;收集鏈路信息&#xff0c;發送給 SkyWalking OAP 服務器。目前支持 SkyWalking、Zikpin、Jaeger 等提供的 Tracing 數據信息。而我們目前采用的是&…

Rust - cargo項目里多個二進制binary crate的編譯運行

目錄 foo - Cargo.toml - src - - main.rs - - bin - - - other-bin.rs將除默認入口文件外待作為二進制crate處理的文件放在src/bin目錄下 方法一&#xff1a; 命令行增加配置項 --bin xxx cargo run --bin foo // 注意! 這里是包名&#xff0c;不是main cargo run --bin o…

SQL基礎理論篇(九):存儲過程

文章目錄 簡介存儲過程的形式定義一個存儲過程使用delimiter定義語句結束符存儲過程中的三種參數類型流控制語句 存儲過程的優缺點參考文獻 簡介 存儲過程Stored Procedure&#xff0c;SQL中的另一個重要應用。 前面說的視圖&#xff0c;只能勉強跟編程中的函數相似&#xff…

MySQL -- JDBC

1、JDBC是什么&#xff1a; 是SUN公司制定的一套接口(interface)。接口都有調用者和實現者。面向接口調用、面向接口寫實現類&#xff0c;這都屬于面向接口編程。 2、在使用JDBC的六個步驟&#xff1a; 1.注冊驅動&#xff08;告訴Java程序&#xff0c;即將連接的是哪個品牌…

業務系統上云后,如何滿足員工移動辦公快速訪問業務系統的需求?

在企業業務上云的大趨勢下&#xff0c;SaaS應用、云端辦公協同工具等多種遠程辦公應用系統開始大規模普及&#xff0c;企業員工可以隨時隨地訪問云上業務數據。然而現實情況卻十分“打臉”&#xff0c;企業隨時隨地要訪問云上業務的需求越迫切&#xff0c;問題就越大。由于多種…

算法通關村第十二關|白銀|字符串經典基礎面試題

1.反轉問題 1.1 反轉字符串 原題&#xff1a;力扣344. 要求原地修改。 public void reverseString(char[] s) {if (s null || s.length() 0) {return;}int n s.length;for (int left 0, right n - 1; left < right; left, right--) {char temp s[left];s[left] s…

小程序訂閱消息

wx.requestSubscribeMessage({tmplIds: [2IdqlWrqSbjAurzIuW8imeK-ftS8gbhYdZ0icdE],success(res) {console.log(res);// 處理用戶授權結果},fail(err) {console.error(err);// 處理授權請求失敗}});

白楊SEO:2B企業營銷是什么?當下主流的短視頻直播平臺有哪些?企業營銷要做短視頻直播選哪個平臺更好?

今天白楊SEO就正式來講講2B企業營銷選擇哪個短視頻直播平臺更好&#xff1f; 圖片在公眾號&#xff1a;白楊SEO上看。 文章大綱提前看&#xff1a; 1、先說說2B企業營銷是什么&#xff1f; 2、當下主流的短視頻直播平臺有哪些&#xff1f; 3、2B企業營銷要做短視頻直播選哪…

重磅!1區、60年老牌期刊被踢?共5本被剔除!11月SCIE/SSCI期刊目錄更新!

期刊動態&#xff1a;2023年11月SCI、SSCI期刊目錄更新 2023年11月20日&#xff0c;科睿唯安更新了WOS期刊目錄&#xff0c;繼上次10月WOS期刊目錄剔除7本SCIE&SSCI期刊之后&#xff0c;此次11月更新又有5本期刊發生變動&#xff0c;其中有4本SCIE期刊被剔除&#xff0c;1…