当前位置: 首页 > article >正文

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连接异常时触发
}

相关文章:

JavaWeb之WebSocket

目录 一、 websocket 概念二、WebSocket原理三、WebSocket特点四、WebSocket应用场景五、Websocket基本使用1、创建Websocket对象2、Websocket事件3、Websocket方法4、前端服务程序 六、聊天室案例1、Tomcat版本&#xff1a;8.0.442、Maven 依赖&#xff1a;3、前端代码4、后端…...

算法2--两数相加

题目描述 解题思路 题目说的很详细了&#xff0c;也就是把每个数倒序写成链表进行输入&#xff0c;然后让你计算两个倒序数组的和&#xff0c;要保证跟预期的结果一样。 首先应该考虑的是两个数组的长度问题&#xff0c;对于链表的每一位进行加法运算&#xff0c;如果两个列表…...

突破边界:Tauri 2.0全局状态管理的原子级实践

精心打造的Tauri 2.0全局状态管理深度指南&#xff0c;融合最新框架特性与企业级实践方案&#xff1a; 一、Tauri 2.0状态管理新范式 1.1 量子态存储模型 #mermaid-svg-paiGRksb0JRQ3TqJ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fil…...

Springboot的jak安装与配置教程

目录 Windows系统 macOS系统 Linux系统 Windows系统 下载JDK&#xff1a; 访问Oracle官网或其他JDK提供商网站&#xff0c;下载适合Windows系统的JDK版本。网站地址&#xff1a;Oracle 甲骨文中国 | 云应用和云平台点击进入下滑&#xff0c;点击进入下载根据自己的系统选择&…...

Axure大屏可视化模板:赋能多领域,开启数据展示新篇章

在当今这个数据爆炸的时代&#xff0c;数据已经成为各行各业的核心资产。然而&#xff0c;如何高效、直观地展示数据&#xff0c;并将其转化为有价值的决策依据&#xff0c;成为了许多企业和组织面临的共同挑战。Axure大屏可视化模板&#xff0c;作为一款强大的数据展示工具&am…...

大模型训练为什么选择交叉熵损失(Cross-Entropy Loss):均方误差(MSE)和交叉熵损失的深入对比

交叉熵损失&#xff1a;深度学习中的基石与洞见 交叉熵损失&#xff08;Cross-Entropy Loss&#xff09;是现代深度学习中分类任务的核心损失函数&#xff0c;尤其在训练大规模模型&#xff08;如 transformers 等大型语言模型 LLM&#xff09;时&#xff0c;几乎无处不在。对…...

C++|GLog开源库的使用 如何实现自定义类型消息日志

参考&#xff1a; C glog使用教程与代码演示 C第三方日志库Glog的安装与使用超详解 GLOG从入门到入门 glog 设置日志级别_glog C版本代码分析 文章目录 日志等级自定义消息创建使用宏定义 日志等级 在 glog 中&#xff0c;日志的严重性是通过 LogSeverity 来区分的&#xff0c…...

cursor常用快捷键(JetBrains Darcula主题风格)

一、基础操作速查 打开/创建项目 打开项目&#xff1a;Ctrl Shift O&#xff08;选择文件夹&#xff09;新建文件&#xff1a;Ctrl N保存文件&#xff1a;Ctrl S关闭当前标签页&#xff1a;Ctrl F4 代码编辑 复制当前行&#xff1a;Ctrl D删除当前行&#xff1a;Ctrl …...

区块链学习总结

Hardhat 是一个用于 Ethereum 智能合约开发 的开发环境&#xff0c;专为 Solidity 语言编写的智能合约提供工具支持。它能够帮助开发者 编译、部署、测试和调试 智能合约&#xff0c;并提供一个本地的以太坊测试网络。 Hardhat 的核心功能 本地开发网络&#xff08;Hardhat Ne…...

《深入剖析鸿蒙生态原生应用:一次开发多端部署的技术革新》

在数字化时代飞速发展的浪潮中&#xff0c;鸿蒙生态以其独特的技术理念和强大的创新能力&#xff0c;为开发者和用户带来了全新的体验。其中&#xff0c;“一次开发多端部署”作为鸿蒙生态原生应用开发的核心技术之一&#xff0c;不仅是技术上的重大突破&#xff0c;更是对未来…...

知识蒸馏:让大模型“瘦身“而不失智慧的魔术

引言&#xff1a;当AI模型需要"减肥" 在人工智能领域&#xff0c;一个有趣的悖论正在上演&#xff1a;大模型的参数规模每年以10倍速度增长&#xff0c;而移动设备的算力却始终受限。GPT-4的1750亿参数需要价值500万美元的GPU集群运行&#xff0c;但现实中的智能设备…...

JavaScript 获取 URL 中参数值的详解

JavaScript 获取 URL 中参数值的详解 1. 了解 URL 参数2. 使用 URLSearchParams 获取参数值2.1 什么是 URLSearchParams&#xff1f;2.2 示例代码2.3 优缺点 3. 使用正则表达式获取参数值3.1 示例代码3.2 分析 4. 自定义解析函数4.1 示例代码4.2 分析 5. 小结与注意事项 在开发…...

识别并脱敏上传到deepseek/chatgpt的文本文件中的身份证/手机号

本文将介绍一种简单高效的方法解决用户在上传文件到DeepSeek、ChatGPT,文心一言,AI等大语言模型平台过程中的身份证号以及手机号等敏感数据识别和脱敏问题。 DeepSeek、ChatGPT,Qwen,Claude等AI平台工具快速的被接受和使用,用户每天上传的文本数据中潜藏着大量敏感信息,…...

ruoyi-vue部署4

1.jdk-linux安装 2.tomcat-linux安装 3.ruoy后台部署 4.nginx-linux安装5.ruoyi前端部署​​​​​​​...

【秣厉科技】LabVIEW工具包——OpenCV 教程(12):机器学习

文章目录 前言机器学习例1&#xff1a;支持向量机&#xff08;SVM&#xff09;做平面向量二分类例2&#xff1a; K邻近算法&#xff08;KNearest&#xff09;实现分类 总结 前言 需要下载安装OpenCV工具包的朋友&#xff0c;请前往 此处 &#xff1b;系统要求&#xff1a;Wind…...

分布式事务解决方案简介

一、分布式事务的挑战 在分布式系统中&#xff0c;多个服务协同完成一个业务操作时&#xff0c;可能会遇到数据一致性问题。传统单体应用的ACID事务无法直接扩展到分布式环境&#xff0c;主要矛盾在于&#xff1a; • 网络不可靠&#xff1a;服务间通信可能失败。 • 并发冲突…...

【leetcode hot 100 17】电话号码的字母组合

分析&#xff1a;当设计关键字“所有组合”时&#xff0c;要考虑深度优先遍历、广度优先遍历&#xff08;层次遍历&#xff09;&#xff0c;其中&#xff1a; 深度优先搜索&#xff1a; 自顶向下的递归实现深搜定义子问题在当前递归层结合子问题结果解决原问题 广度优先搜索 利…...

UI数据处理新隐私保护:确保用户新信息安全

hello宝子们...我们是艾斯视觉擅长ui设计和前端数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩! 在这个数字时代&#xff0c;我们的个人信息似乎无处不在。从社交媒体上的点滴分享&#xff0c;到在线…...

【Javascrip】Javascript练习01 REST API using Express.js.

针对该问题的项目路径 要求部分 what you need to doReview the tasks provided in the section below.Obtain the boilerplate code.Use your local development environment to implement a solution.Upload your solution for marking via Gradescope. There is no attempt…...

分析K8S中Node状态为`NotReady`问题

在Kubernetes&#xff08;k8s&#xff09;集群中&#xff0c;Node状态为NotReady通常意味着节点上存在某些问题&#xff0c;下面为你分析正常情况下节点应运行的容器以及解决NotReady状态的方法。 正常情况下Node节点应运行的容器 1. kubelet kubelet是节点上的核心组件&…...

小样本学习综述

小样本学习综述 &#x1f4d5;[1]潘雪玲,李国和,郑艺峰. 面向深度网络的小样本学习综述 [J]. 计算机应用研究, 2023, 40 (10): 2881-28882895. DOI:10.19734/j.issn.1001-3695.2023.02.0074. 主要是该论文的一些摘要。 小样本学习旨在利用较少目标数据训练模型快速学习的。 …...

挂谷问题与挂谷猜想:从平面转针到高维拓扑

挂谷问题与挂谷猜想&#xff1a;从平面转针到高维拓扑 目录 挂谷问题的起源数学定义与基本性质研究进展挂谷集合与挂谷猜想王虹与Joshua Zahl的突破意义与影响 挂谷问题的起源 1917年&#xff0c;日本数学家挂谷宗一(かけや そういち Soichi Kakeya&#xff0c;1886-1947)提…...

火语言RPA--表格数据导出

表格数据导出 &#x1f6a9;【组件功能】&#xff1a;导出表格内数据到指定的文件 配置预览 配置说明 导出格式 Excel&#xff1a;导出Excel文档格式&#xff0c;CSV:导出CSV数据格式。 导出文件夹 支持T或# 导出文件需要保存的文件夹路径。 导出文件名支持T或# 导出文…...

数学建模:MATLAB卷积神经网络

一、简述 卷积神经网络是一种处理具有网格结构数据的深度学习模型&#xff0c;由输入层、卷积层、池化层、全连接层、输出层组成。 输出层&#xff1a;将图像转换为其对应的由像素值构成的二维矩阵&#xff0c;并存储二维矩阵 卷积层&#xff1a;提取图像的底层特征&#xf…...

Vue3 基础语法指南:响应式系统与 Ref 应用

1、Reactive 的深度响应式 1.1、基本用法 vue <script setup> import { reactive } from vueconst state reactive({count: 0,user: {name: Alice,age: 30} })const increment () > state.count const updateName () > state.user.name Bob </script>1…...

学习笔记:黑马程序员JavaWeb开发教程(2025.3.21)

10.10 案例-员工管理-删除员工 前端中有两个删除按键&#xff0c;一个是删除员工&#xff0c;一个是批量删除&#xff0c;我们只需要将删除员工作为特殊的批量删除&#xff0c;就是只删除一个&#xff0c;开发一个接口就行 用id in &#xff08;&#xff09;来批量删除&…...

xLua_003 Lua访问C#

1、new C# 对象&#xff08;创建游戏物体&#xff09; LuaCallCSharp.cs using UnityEngine; using XLua;public class LuaCallCSharp : MonoBehaviour {public LuaEnv env null;void Start(){LuaEnv env new LuaEnv();env.DoString("requireLuaCallCSharp");}pr…...

mysql 磐维(opengauss)tidb误删数据之高级恢复

Mysql参考&#xff1a; Mysql 8.0 XtraBackupMysqlbinlog 完全恢复 - 墨天轮 Mysql 8.0 XtraBackupMysqlbinlog 完全恢复[TOC]# 一、安装mysql 8.0.19## 1.1https://www.modb.pro/db/509223MySQL 的全量备份、增量备份与 Binlog 时间点恢复_mysqlbinlog自动备份吗-CSDN博客文章…...

区块链技术在供应链管理中的应用与创新

在当今全球化的商业环境中&#xff0c;供应链管理的复杂性与日俱增。从原材料采购到最终产品交付&#xff0c;涉及众多环节和参与者&#xff0c;信息的透明度、准确性和安全性至关重要。区块链技术的出现&#xff0c;为供应链管理带来了全新的解决方案&#xff0c;正在逐步改变…...

字符指针的三道例题+算法改进

目录 一.杨氏矩阵 1.初级 2.想把下标带回来 二.字符串左旋 算法改进 三.判断是否为字符串旋转结果 算法改进 四. 3个字符函数 1.strcat 2.strncat 3.strstr 一.杨氏矩阵 数字矩阵&#xff0c;每行从左到右递增&#xff0c;每列从上到下递增&#xff0c;编写程序在矩…...