JavaWeb之WebSocket

目錄

    • 一、 websocket 概念
    • 二、WebSocket原理
    • 三、WebSocket特點
    • 四、WebSocket應用場景
    • 五、Websocket基本使用
      • 1、創建Websocket對象
      • 2、Websocket事件
      • 3、Websocket方法
      • 4、前端服務程序
    • 六、聊天室案例
      • 1、Tomcat版本:8.0.44
      • 2、Maven 依賴:
      • 3、前端代碼
      • 4、后端代碼

一、 websocket 概念

WebSocket是HTML5提供的一種瀏覽器與服務器進行全雙工通訊的網絡技術,屬于應用層協議。它基于TCP傳輸協議,并復用HTTP的握手通道。瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接, 并進行雙向數據傳輸。WebSocket 的出現就解決了半雙工通信的弊端。它最大的特點是:服務器可以向客戶端主動推動消息,客戶端也可以主動向服務器推送消息。

獲取到最新的信息,只有再次發起客戶端請求,服務器端才會返回結果。但是服務器端不能做到推送消息給客戶端,當然我們可以使用輪詢,查看服務器有沒有新的消息

二、WebSocket原理

客戶端向 WebSocket 服務器通知(notify)一個帶有所有接收者ID(recipients IDs)的事件(event),服務器接收后立即通知所有活躍的(active)客戶端,只有ID在接收者ID序列中的客戶端才會處理這個事件。
在這里插入圖片描述

三、WebSocket特點

  • 支持雙向通信,實時性更強,相對于HTTP請求需要等待客戶端發起請求服務端才能響應,延遲明顯更少
  • 可以發送文本,也可以發送二進制數據
  • 建立在TCP協議之上,服務端的實現比較容易
  • 數據格式比較輕量,性能開銷小,通信高效
  • 沒有同源限制,客戶端可以與任意服務器通信
  • 協議標識符是ws(如果加密,則為wss),服務器網址就是 URL
  • 與 HTTP 協議有著良好的兼容性。默認端口也是80和443,并且握手階段采用 HTTP 協議,因此握手時不容易屏蔽,能通過各種 HTTP 代理服務器

四、WebSocket應用場景

  • 彈幕
  • 媒體聊天
  • 協同編輯
  • 基于位置的應用
  • 體育實況更新
  • 股票基金報價實時更新

五、Websocket基本使用

在HTML5中,瀏覽器已經實現了websocket的API,直接使用即可:WebSocket-MDN

1、創建Websocket對象

// 參數1: url:連接的websocket屬性
// 參數2: protocol,可選的,指定連接的協議
// var socket = new WebSocket('ws://echo.websocket.org')
var Socket = new WebSocket(url, [protocol] );

2、Websocket事件

事件事件處理程序描述
openSocket.onopen連接建立時觸發
messageSocket.onmessage客戶端接收服務端數據時觸發
errorSocket.onerror通信發生錯誤時觸發
closeSocket.onclose連接關閉時觸發

3、Websocket方法

方法描述
Socket.send()使用連接發送數據
Socket.close()關閉連接

WebSocket的狀態

可以通過讀取readyState的屬性值來獲取WebSocket對象的狀態,readyState屬性存在以下幾種屬性值。

  • CONNECTING(數字值為0),表示正在連接;
  • OPEN(數字值為1),表示已建立連接;
  • CLOSING(數字值為2),表示正在關閉連接;
  • CLOSED(數字值為3),表示已關閉鏈接。

4、前端服務程序

// 導入第三方模塊
const ws = require('nodejs-websocket')
var websocket = new WebSocket("ws://172.16.116.22:8088/WebSocket/chatServer/"+nickname);
// websocket占用的端口號
const PORT = 3000const server = ws.createServer(connect => {console.log('新的連接')// 接收到客戶端的文本內容時觸發connect.on('text', str => {console.log('接收:' + str)// 把接收到的字符串轉換成大寫,并且給客戶端響應connect.sendText(str.toUpperCase() + '!!!!')})// 監聽關閉事件connect.on('close', () => {console.log('連接關閉了')})// 監聽錯誤事件, 比如瀏覽器關閉了連接,或者發送的數據格式不對等connect.on('error', err => {console.log('連接異常')})
})// 啟動websocket服務
server.listen(PORT, function() {console.log(`websocket server listening on ${PORT}`)
})

WebSocket的前端API

  • WebSocket需要接收一個url參數,然后調用WebSocket對象的構造器來建立與服務器之間的通信鏈接。
    websocket = new WebSocket(“ws://localhost:8088/chatServer/”+nickname);

    • URL字符串必須以 “ws” 或 “wss”(加密通信)開頭。
    • 利用上面的代碼,我們的通信連接建立之后,就可以進行客戶端與服務器端的雙向通信了。可以使用WebSocket對象的send方法對服務器發送數據,但是只能發送文本數據(我們可以使用JSON對象把任何js對象轉換成文本數據后再進行發送)。
  • websocket.send(“data”);

    • websocket.send(“data”);
  • websocket.onmessage = function(event) {

    websocket.onmessage = function(event) {var data = event.data;
    }
    
  • 監聽socket的打開事件

    • 通過獲取onopen事件來監聽socket的打開事件。如下代碼:
      websocket.onopen = function(event) {
      // 開始通信時的處理
      }
      
  • 通過獲取onclose事件來監聽socket的關閉事件。如下代碼:

    websocket.onclose = function(event) {
    // 通信結束時的處理
    }
    
  • 關閉socket
    通過close方法來關閉socket, 如下代碼:

    websocket.close();

六、聊天室案例

1、Tomcat版本:8.0.44

2、Maven 依賴:

<dependency><groupId>javax.websocket</groupId><artifactId>javax.websocket-api</artifactId><version>1.1</version><scope>provided</scope></dependency>
<!--    <dependency>-->
<!--      <groupId>javax</groupId>-->
<!--      <artifactId>javaee-api</artifactId>-->
<!--      <version>8.0</version>-->
<!--    </dependency>--><!--    導入servlet-->
<!--    處理JSON-->
<!--    <dependency>-->
<!--      <groupId>com.alibaba</groupId>-->
<!--      <artifactId>fastjson</artifactId>-->
<!--      <version> 1.2.58</version>-->
<!--    </dependency>--><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.5</version></dependency>

3、前端代碼

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>聊天室</title><link rel="stylesheet" href=""><style type="text/css" media="screen">*{margin: 0px;padding: 0px;}.all{width: 900px;height: 700px;margin: 0 auto;}.all-top{width: 100%;height: 30px;background-color: yellow;}.all-center{width: 100%;height: 570px;/*添加滾動條*/overflow-y: scroll;background-color: pink;}.all-bottom{width: 100%;height: 100px;background-color: green;}.number{width: 100%;height: 40px;background-color: green;text-align: center;color: #fff;font-size: 20px;}</style>
</head>
<body>
<div class="all"><div class="all-top">昵稱:<input type="text" id="nickname"><button type="button" onclick="connect()">鏈接</button></div><div class="number" id="number">當前在線人數:0</div><div class="all-center" id="message">IP:172.16.116.22 <br>端口是:8088<br>工程是:WebSocket<br>接口是:chatServer<br></div><div class="all-bottom">發送信息:<input type="text" id="msg"><button type="button" onclick="sendMsg()">發送</button></div>
</div>
</body>
<script  type="text/javascript">/*ws:// 代表 websocket*//*127.0.0.1:8088 后端服務地址*//*WebSocket 工程名稱*//*chatServer 對應@ServerEndpoint注解的value屬性*/var websocket = null;//鏈接后端服務器function connect(){if(websocket != null){return;}var nickname = document.getElementById("nickname").value;console.log(nickname)websocket = new WebSocket("ws://localhost:8088/chatServer/"+nickname);//鏈接成功時觸發websocket.onopen = function(){setMsgToPage("你鏈接上聊天服務器了!");}//收到服務器端信息觸發websocket.onmessage = function(event){var data = JSON.parse(event.data)if(data.code == 1){//接收到的是聊天信息var umsg = data.name + "說:" + data.msg;setMsgToPage(umsg);}else if(data.code == 2){//上線document.getElementById("number").innerHTML = "當前在線人數:"+data.number+"人";setMsgToPage("艦長:"+data.name+"進入直播間");}else if(data.code == 3){//下線document.getElementById("number").innerHTML = "當前在線人數:"+data.number+"人";setMsgToPage("艦長:"+data.name+"離開直播間");}}//發生異常時觸發websocket.onerror = function(){}//鏈接關閉觸發websocket.onclose = function(){}}//用來給后端發送信息function sendMsg(){//獲取用戶輸入的信息var msg = document.getElementById("msg").value;//給后端發送websocket.send(msg);}//把信息賦值到頁面function setMsgToPage(msg){document.getElementById("message").innerHTML += msg + "</br>";}</script>
</html>

4、后端代碼

import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;//WebSocket服務
//value是WebSocket接口地址
@ServerEndpoint(value="/chatServer/{userName}")
public class ChatServer {//session使用來保存用戶狀態信息的//CopyOnWriteArraySet == set 但是CopyOnWriteArraySet是線程安全的private static CopyOnWriteArraySet<Session> socketSet = new CopyOnWriteArraySet<Session>();//1.0用戶連接時觸發@OnOpenpublic void onOpen(@PathParam("userName")String name,Session session){System.out.println("用戶開始鏈接");//Session 用戶的信息 用戶的狀態socketSet.add(session);for(Session s:socketSet){//給所有在集合內的用戶廣播信息try {if(s.isOpen()){s.getBasicRemote().sendText("{\"code\":2,\"number\":\""+socketSet.size()+"\",\"name\":\""+name+"\"}");}else{s.close();}} catch (IOException e) {e.printStackTrace();}}}//2.0接收到用戶信息時觸發@OnMessagepublic void onMessage(@PathParam("userName")String name,String data,Session session){for(Session s:socketSet){//給所有在集合內的用戶廣播信息try {if(s.isOpen()){s.getBasicRemote().sendText("{\"code\":1,\"name\":\""+name+"\",\"msg\":\""+data+"\"}");}else{s.close();}} catch (IOException e) {e.printStackTrace();}}}//3.0用戶下線時觸發@OnClosepublic void onClose(@PathParam("userName")String name,Session session){//用戶下線時刪除這個socketSet.remove(session);for(Session s:socketSet){//給所有在集合內的用戶廣播信息try {if(s.isOpen()){s.getBasicRemote().sendText("{\"code\":3,\"number\":\""+socketSet.size()+"\",\"name\":\""+name+"\"}");}else{s.close();}} catch (IOException e) {e.printStackTrace();}}}//4.0連接異常時觸發
}

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

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

相關文章

Unity Shader編程】之透明物體渲染

以下是針對您提出的關于 Unity Shader 渲染 Pass 的查看方法、多個 Pass 的影響、Pass 的含義&#xff0c;以及 Unity 渲染物體的流程和處理多個透明/半透明/不透明物體的詳細解答。 1. Unity Shader 渲染 Pass 的查看方法 查看 Pass 的方法 通過 Shader 代碼&#xff1a; 打開…

字符指針的三道例題+算法改進

目錄 一.楊氏矩陣 1.初級 2.想把下標帶回來 二.字符串左旋 算法改進 三.判斷是否為字符串旋轉結果 算法改進 四. 3個字符函數 1.strcat 2.strncat 3.strstr 一.楊氏矩陣 數字矩陣&#xff0c;每行從左到右遞增&#xff0c;每列從上到下遞增&#xff0c;編寫程序在矩…

VSCode中搜索插件顯示“提取擴展時出錯。Failed to fetch”問題解決!

大致的問題如下&#xff0c;在VSCode的插件商店搜索插件時提示如下&#xff1a; 導致的情況有以下幾點&#xff1a; 1、代理問題&#xff0c;如果是代理引起的&#xff0c;可以繼續使用代理后也能搜索和安裝插件。 2、還有可能是你的所連接的網絡設置了防火墻&#xff0c;比較…

雙指針(2)—三數之和

文章目錄 題目解析解法&#xff08;排序雙指針&#xff09;&#xff1a;哈希解法附加Java代碼&#xff1a; 力扣題目&#xff1a;三數之和 題目解析 解法&#xff08;排序雙指針&#xff09;&#xff1a; **算法思路&#xff1a;** 本題與兩數之和類似&#xff0c;是?常經典的…

設計一套水產養殖系統

設計一套水產養殖系統 引言 水產養殖在全球糧食安全和經濟發展中日益重要。它不僅為不斷增長的人口提供了重要的蛋白質來源&#xff0c;還在許多地區創造了就業機會并促進了經濟增長 。全球超過一半的人類消費的海產品來自水產養殖&#xff0c;并且這一比例預計將繼續上升 。…

統計可重復列表中的TOP N

文章目錄 方案1&#xff1a;HashMap統計 全排序實現步驟&#xff1a;代碼實現&#xff1a;優缺點&#xff1a; 方案2&#xff1a;HashMap統計 最小堆&#xff08;優先隊列&#xff09;實現步驟&#xff1a;代碼實現&#xff1a;優缺點&#xff1a; 方案3&#xff1a;Java Str…

JVM 知識點梳理

JDK 、JRE、JVM JDK&#xff08; Java Development Kit &#xff09; Java開發工具包 JRE 開發命令工具&#xff08;運行java.exe、編譯javac.exe、javaw.exe&#xff09; JRE&#xff08; Java Runtime Environment &#xff09;Java運行環境 JVM Java核心類庫&#xff08;l…

淘寶歷史價格數據獲取指南:API 與爬蟲方案的合法性與效率對比

引言 在淘寶平臺的購物生態中&#xff0c;消費者希望通過了解商品歷史價格來判斷當前價格是否實惠&#xff0c;商家也需要借助歷史價格數據制定合理的營銷策略、分析市場趨勢。獲取淘寶商品歷史價格數據主要有 API 和爬蟲兩種方案&#xff0c;它們在合法性與效率上存在顯著差異…

DeepSeek-R1論文深度解析:純強化學習如何引爆LLM推理革命?

技術突破&#xff1a;從“無監督”到“自主進化”的跨越 paper &#xff1a;https://arxiv.org/pdf/2501.12948目錄 技術突破&#xff1a;從“無監督”到“自主進化”的跨越1 DeepSeek-R1-Zero&#xff1a; RLnoSFT1.1 R1-Zero&#xff1a; GRPO&#xff08;Group Relative Po…

表格標題豎直

使用文本方式使表格怎么豎列 思路&#xff1a;表格豎直書寫&#xff0c;里面的內容水平書寫 使用到的是css中的文本效果&#xff1a; writing-mode&#xff1a;書寫方式horizontal-tb&#xff1a;水平vertical-rl&#xff1a;豎直<style>table {writing-mode: vertical…

AI+視頻賦能智慧農業:EasyCVR打造全域可視化農場監管平臺

隨著科技的飛速發展&#xff0c;傳統農業正加速向智慧農業轉型&#xff0c;農場管理也迎來了前所未有的變革機遇。在這一進程中&#xff0c;如何有效整合先進的信息技術&#xff0c;實現農場的精準化、智能化管理&#xff0c;成為了擺在農場主和農業管理者面前的關鍵課題。 基于…

HarmonyOS鴻蒙開發 BuilderParam在父組件的Builder的點擊事件報錯:Error message:is not callable

HarmonyOS鴻蒙開發 BuilderParam在父組件的Builder的點擊事件報錯&#xff1a;Error message:is not callable 最近在鴻蒙開發過程中&#xff0c;UI做好了&#xff0c;根據列表item進行點擊跳轉&#xff0c;報錯了 報錯信息如下 Error message:is not callable Stacktrace:at…

簡化神經元模型6 -- Hindmarsh-Rose Model

Hindmarsh-Rose 模型 目錄 0. 寫在前面 1. Hindmarsh-Rose 模型的定義 2. Hindmarsh-Rose 模型簇發放的動力學機制 3. Hindmarsh-Rose 模型的其他發放模式 4. 分析過程所用到的一系列 BrainPy 代碼 0. 寫在前面 前面介紹了: Hodgkin-Huxley Model 簡化神經元模型1 – LIF M…

第六屆電氣、電子信息與通信工程國際學術會議 (EEICE 2025)

重要信息 官網&#xff1a;www.eeice.net&#xff08;點擊了解參會投稿等&#xff09; 時間&#xff1a;2025年4月18-20日 地點&#xff1a;中國-深圳技術大學 簡介 第六屆電氣、電子信息與通信工程 (EEICE 2025&#xff09;將于2025年4月18-20日在中國深圳召開。 EEICE 20…

計算機操作系統(三) 操作系統的特性、運行環境與核心功能(附帶圖譜更好對比理解))

計算機操作系統&#xff08;三&#xff09; 操作系統的特性、運行環境與核心功能 前言一、操作系統的基本特性1.1 并發1.2 共享1.3 虛擬1.4 異步 二、操作系統的運行環境2.1 硬件支持2.2 操作系統內核2.3 處理機的雙重工作模式2.4 中斷與異常 三、操作系統的主要功能3.1 處理機…

Linux(Ubuntu)系統安裝Docker與Docker Compose完整指南

本文是為需要在Ubuntu系統部署容器服務的開發者準備的詳細教程。我們將分兩個主要部分講解&#xff1a;Docker引擎的標準安裝流程和Docker Compose的配置方法。所有操作均在終端執行&#xff0c;建議使用Ubuntu 18.04及以上版本。 一、Docker引擎安裝全流程 &#xff08;總耗時…

批量將 PPT 轉換為PDF/XPS/JPG圖片等其它格式

PPT 文檔經常有轉換為其它格式的需求&#xff0c;比如將 PPT 轉換為 PDF、將 PPT 轉換為圖片、生成 PPT 預覽圖等&#xff0c;這在某些場景下非常的有用&#xff0c;今天給大家介紹的就是如何批量將 PDF 轉換為 PDF、JPG、Tiff 等多種格式的操作。 在工作中我們經常需要接觸 PP…

c庫、POSIX庫、C++庫、boost庫之間的區別和聯系

文章目錄 一、區別1. 定義和來源2. 功能范圍3. 可移植性4. 語言支持5. 維護和更新 二、聯系1. 相互補充2. 部分功能重疊3. 共同促進編程發展4. 代碼兼容性 三、總結 一、區別 1. 定義和來源 C 庫函數&#xff1a;由 ANSI C 和 ISO C 標準定義&#xff0c;是 C 語言編程的基礎…

響應壓縮導致的接口請求response沒有響應體問題排查

目錄 一、背景二、排查過程三、解決方法四、學習與思考-響應壓縮&#xff08;一&#xff09;可能原因&#xff08;二&#xff09;深入排查&#xff08;三&#xff09;注意 一、背景 接口發布到測試環境&#xff0c;測試同學說沒有數據 二、排查過程 1、本地用相同的參數、相…

JVM中的運行時常量池詳解

運行時常量池&#xff08;Runtime Constant Pool&#xff09;是每一個類或接口的常量池&#xff08;Constant_Pool&#xff09;的運行時表示形式&#xff0c;它包括了若干種不同的常量&#xff1a;從編譯期可知的數值字面量到必須運行期解析后才能獲得的方法或字段引用。運行時…