Java - WebSocket

一、WebSocket

1.1、WebSocket概念

WebSocket是一种协议,用于在Web应用程序和服务器之间建立实时、双向的通信连接。它通过一个单一的TCP连接提供了持久化连接,这使得Web应用程序可以更加实时地传递数据。WebSocket协议最初由W3C开发,并于2011年成为标准。

1.2、WebSocket协议

WebSocket 协议是一种基于TCP的协议,用于在客户端和服务器之间建立持久连接,并且可以在这个连接上实时地交换数据。WebSocket协议有自己的握手协议,用于建立连接,也有自己的数据传输格式。

当客户端发送一个 WebSocket 请求时,服务器将发送一个协议响应以确认请求。在握手期间,客户端和服务器将协商使用的协议版本、支持的子协议、支持的扩展选项等。一旦握手完成,连接将保持打开状态,客户端和服务器就可以在连接上实时地传递数据。

WebSocket 协议使用的是双向数据传输,即客户端和服务器都可以在任意时间向对方发送数据,而不需要等待对方的请求。它支持二进制数据和文本数据,可以自由地在它们之间进行转换。

总之,WebSocket协议是一种可靠的、高效的、双向的、持久的通信协议,它适用于需要实时通信的Web应用程序,如在线游戏、实时聊天等

1.3、WebSocket原理

WebSocket 生命周期描述了 WebSocket 连接从创建到关闭的过程。一个 WebSocket 连接包含以下四个主要阶段:

  • 连接建立阶段(Connection Establishment):在这个阶段,客户端和服务器之间的 WebSocket 连接被建立。客户端发送一个 WebSocket 握手请求,服务器响应一个握手响应,然后连接就被建立了。
  • 连接开放阶段(Connection Open):在这个阶段,WebSocket 连接已经建立并开放,客户端和服务器可以在连接上互相发送数据。
  • 连接关闭阶段(Connection Closing):在这个阶段,一个 WebSocket 连接即将被关闭。它可以被客户端或服务器发起,通过发送一个关闭帧来关闭连接。
  • 连接关闭完成阶段(Connection Closed):在这个阶段,WebSocket 连接已经完全关闭。客户端和服务器之间的任何交互都将无效

客户端依靠发起HTTP握手,告诉服务端进行WebSocket协议通讯,并告知WebSocket协议版本。服务端确认协议版本,升级为WebSocket协议。之后如果有数据需要推送,会主动推送给客户端

请求头Request Headers

GET /test HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: sehfiowqweuq1psd==
Sec-WebSocket-Protocol: v10.stomp, v11.stomp, v12.stomp
Origin: http://hello.com
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Version: 13

首先客户端(如浏览器)发出带有特殊消息头(Upgrade、Connection)的请求到服务器,服务器判断是否支持升级,支持则返回响应状态码101,表示协议升级成功,对于WebSocket就是握手成功。其中关键的字段就是Upgrade,Connection,告诉 Apache 、 Nginx 等服务器:注意啦,发起的是Websocket协议,不再 使用原先的HTTP。其中,Sec-WebSocket-Key当成是请求id就好了。

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HaA6EjhHRejpHyuO0yBnY4J4n3A=
Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
Sec-WebSocket-Protocol: v12.stomp

Sec-WebSocket-Accept的字段值是由握手请求中的Sec-WebSocket-Key的字段值生成的。成功握手确立WebSocket连接之后,通信时不再使用HTTP的数据帧,而采用WebSocket独立的数据帧

1.4、 应用场景

实时聊天:聊天应用需要实时的消息传递,WebSocket 提供了高效的解决方案。

在线游戏:游戏中的实时交互(例如玩家动作和状态更新)可以通过 WebSocket 高效地处理。

股票市场:股票和金融市场应用需要实时更新数据,WebSocket 能够提供实时行情和交易信息。

实时通知:例如社交网络应用中的即时通知和更新。

协作应用:如实时文档编辑和在线协作工具,可以使用 WebSocket 实现多用户之间的同步更新。

WebSocket 协议在许多现代网络应用中扮演了重要角色,特别是在需要高频率数据交换和低延迟响应的场景中

1.5、WebSocket优劣势

WebSocket优势:

  • 实时性:由于WebSocket的持久化连接,它可以实现实时的数据传输,避免了Web应用程序需要不断地发送请求以获取最新数据的情况。
  • 双向通信:WebSocket协议支持双向通信,这意味着服务器可以主动向客户端发送数据,而不需要客户端发送请求。
  • 减少网络负载:由于WebSocket的持久化连接,它可以减少HTTP请求的数量,从而减少了网络负载。

WebSocket劣势:

  • 需要浏览器和服务器都支持:WebSocket是一种相对新的技术,需要浏览器和服务器都支持。一些旧的浏览器和服务器可能不支持WebSocket。
  • 需要额外的开销:WebSocket需要在服务器上维护长时间的连接,这需要额外的开销,包括内存和CPU。
  • 安全问题:由于WebSocket允许服务器主动向客户端发送数据,可能会存在安全问题。服务器必须保证只向合法的客户端发送数据

1.6、http和websocket区别

(1)WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息;HTTP是单向的

(2)WebSocket是需要浏览器和服务器握手进行建立连接的;而HTTP是浏览器发起向服务器的连接,服务器预先并不知道这个连接

二、Java中使用WebSocket

2.1、Java WebSocket API编写WebSocket

2.1.1、WebSocket服务器的搭建方法

在Java中搭建WebSocket服务器的方法如下:

1、首先,需要引入Java WebSocket API库。可以从Maven仓库下载Java WebSocket API依赖,或者直接将相关jar文件添加到项目中。

2、创建一个WebSocket服务器类,实现javax.websocket.Endpoint接口。这个类将作为WebSocket服务器的入口点,并定义了处理WebSocket连接和消息的方法。

3、在服务器类中,重写以下方法:

@OnOpen:注解用于标记一个方法,当WebSocket与客户端成功建立连接时,这个方法将被调用。

@OnMessage:注解标记的方法会在收到客户端发送的消息时被调用。在示例中,收到消息后会打印消息内容,并将响应消息发送回客户端。

@OnClose:注解标记的方法会在WebSocket关闭时被调用。

@OnError:注解标记的方法会在发生错误时被调用。

在类上使用@ServerEndpoint注解,将这个类声明为一个WebSocket端点。/websocket是WebSocket的URI,客户端可以通过这个URI来连接到这个WebSocket端点。

4、使用javax.websocket.server.ServerEndpoint注解标记服务器类,指定WebSocket的URL路径。

5、创建一个WebSocket服务器容器类,用来启动和管理WebSocket服务器。可以使用javax.websocket.server.ServerEndpointConfig的Builder类创建一个服务器配置对象,将服务器类和URL路径关联起来,并配置其他相关信息。

6、使用WebSocket服务器容器类的create方法创建一个WebSocket服务器实例。

7、启动WebSocket服务器,可以使用Server.start()方法

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;@ServerEndpoint("/websocket")
public class WebSocketServer {@OnOpenpublic void onOpen(Session session) {// 在连接打开时执行的操作}@OnClosepublic void onClose(Session session) {// 在连接关闭时执行的操作}@OnMessagepublic void onMessage(String message, Session session) {// 处理收到的消息}
}

编写配置类

// 需要注入Bean的话必须声明为配置类
@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}
}

 调用:

import javax.websocket.server.ServerEndpointConfig;public class WebSocketServerContainer {public static void main(String[] args) {ServerEndpointConfig serverConfig = ServerEndpointConfig.Builder.create(WebSocketServer.class, "/websocket").build();WebSocketContainer container = ContainerProvider.getWebSocketContainer();try {container.connectToServer(serverConfig, new URI("ws://localhost:8080/"));} catch (Exception e) {e.printStackTrace();}}
}

:这里监听的地址不可以是 "ws" 不然会报错,可能这是关键字吧,毕竟我们的协议就叫 ws 

2.1.2、Vue + JS 实现客户端

<template><div class="app-container home"><el-row :gutter="20"><el-col :sm="24" :lg="24"><h1>集成websocket测试</h1></el-col></el-row><el-row :gutter="20"><el-col :sm="24" :lg="24"><div><el-input v-model="url" type="text" style="width: 20%" /> &nbsp;&nbsp;<el-button @click="join" type="primary">连接</el-button><el-button @click="exit" type="danger">断开</el-button><el-button @click="resetForm" type="success">重置</el-button><br /><br /><el-input type="textarea" v-model="message" :rows="9" /><br /><br /><el-button type="success" @click="send">发送消息</el-button><br /><br />返回内容<el-input type="textarea" v-model="text_content" :rows="9" /><br /><br /></div></el-col></el-row></div>
</template><script>
import { getToken } from "@/utils/auth";export default {name: "Index",data() {return {url: "ws://127.0.0.1:8080/websocket/message",message: "",text_content: "",ws: null,headers: {Authorization: "Bearer " + getToken(),},};},methods: {join() {const wsuri = this.url;// this.ws = new WebSocket(wsuri);this.ws = new WebSocket(wsuri, [getToken()]);const self = this;// 连接成功后调用this.ws.onopen = function (event) {self.text_content = self.text_content + "WebSocket连接成功!" + "\n";};this.ws.onerror = function (event) {self.text_content = self.text_content + "WebSocket连接发生错误!" + "\n";};// 接收后端消息this.ws.onmessage = function (event) {self.text_content = self.text_content + event.data + "\n";};// 关闭连接时调用this.ws.onclose = function (event) {self.text_content = self.text_content + "已经关闭连接!" + "\n";};},exit() {if (this.ws) {this.ws.close();this.ws = null;}},send() {if (this.ws) {this.ws.send(this.message);} else {alert("未连接到服务器");}},//重置resetForm() {this.message = "";this.text_content = "";},},
};
</script>

2.2、Spring Boot集成WebSocket

2.2.1、添加依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2.2.2、配置WebSocket

应用程序中,需要配置WebSocket。创建一个新的Java类,并添加注。@ServerEndpoint(“/websocket”)。这将指定WebSocket服务端的端点。

在此类中,需要实现几个方法:

import javax.websocket.OnClose;import javax.websocket.OnMessage;import javax.websocket.OnOpen;import javax.websocket.Session;import javax.websocket.server.ServerEndpoint;@ServerEndpoint("/websocket")
public class WebSocketServer {@OnOpenpublic void onOpen(Session session) {System.out.println("Connection opened: " + session.getId());sessions.add(session);}@OnMessagepublic void onMessage(Session session, String message) throws IOException {System.out.println("Received message: " + message);session.getBasicRemote().sendText("Server received: " + message);}@OnClosepublic void onClose(Session session) {System.out.println("Connection closed: " + session.getId());sessions.remove(session);}private static final Set<Session> sessions = Collections.synchronizedSet(new HashSet<Session>());
}

2.2.3、处理WebSocket消息

在@OnMessage方法中,可以处理WebSocket客户端发送的消息,并向客户端发送响应。下面是一个简单的示例代码:

@OnMessage
public void onMessage(Session session, String message) throws IOException {System.out.println("Received message: " + message);session.getBasicRemote().sendText("Server received: " + message);
}

在此代码中,我们简单地打印出收到的消息,并向客户端发送响应。

关闭WebSocket连接

在@OnClose方法中,可以删除连接并做一些清理工作。下面是一个示例代码:

@OnClose
public void onClose(Session session) {System.out.println("Connection closed: " + session.getId());sessions.remove(session);
}

在此代码中,我们从连接池中删除连接,并打印出连接已关闭的消息。

配置WebSocket支持

最后,需要配置Spring Boot以支持WebSocket。创建一个新的Java类,并添加注释@Configuration和@EnableWebSocket。然后,需要覆盖方法registerWebSocketHandlers(),并指定WebSocket处理程序。下面是一个示例代码:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(new WebSocketServer(), "/websocket").setAllowedOrigins("*");}
}

在此代码中,我们创建了一个新的WebSocketServer对象,并将其添加到WebSocket处理程序中。我们还指定了WebSocket端点(/websocket)和允许的来源(*)。

三、PostMan调用

3.1、Websocket在线模拟请求工具

访问访问地址:http://www.jsons.cn/websocket/

具有进行连接、断开、模拟发送数据等功能。

(请求时注意连接格式为 ws://IP或域名:端口(示例 ws://127.0.0.1:8089/websocket/devices)

3.2、Postman

使用新版的Postman

1、建立 WebSocket 连接

在 File–> New 页面,选择 WebSocket Request,即可创建一个 WebSocket 模拟请求。

2、模拟数据交互

在地址栏中输入相应的 WebSocket 请求地址,点击地址栏右侧的 “Connect” 按钮,即可建立连接。

连接建立成功后,在 Message 的信息栏中输入模拟数据,点击 “Send” 按钮,即可与服务端进行数据交互。

优势:

支持多种数据格式

如:Text、JSON、XML、HTML、Binary等;

支持对交互信息进行格式化显示

如:Text、JSON、XML、HTML等;

支持对交互数据进行模糊搜索、筛选过滤、清空等操作;

交互数据按照时间倒序显示,更便于查看最新的数据。

3、断开 WebSocket 连接

如果调试结束,点击地址栏右侧的 “Disconnect” 按钮,即可断开与 WebSocket 服务端的连接

可参考

WebSocket详解及使用教程:打造高效的实时通信(二)_利用websocket进行聊天-CSDN博客


Java中使用WebSocket的几种方式_java_脚本之家

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/66589.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

stm32 no connect target

解决 STM32 报错 “no target connected” 的方法 前言 stm32最小系统在下载程序是一直报错&#xff1a;no target connected&#xff0c;试了很多办法成功不了&#xff0c;最后将芯片擦除了才成功。 一、问题描述 当时是写flash的时候写到ST Link 存储的地方了。 之后就不…

Open3D计算点云粗糙度(方法一)【2025最新版】

目录 一、Roughness二、代码实现三、结果展示博客长期更新,本文最近更新时间为:2025年1月18日。 一、Roughness 通过菜单栏的Tools > Other > Roughness找到该功能。 这个工具可以估计点云的“粗糙度”。 选择一个或几个点云,然后启动这个工具。 CloudCompare只会询问…

窥探QCC518x/308x系列与手机之间的蓝牙HCI记录与分析 - 手机篇

今天要介绍给大家的是, 当我们在开发高通耳机时如果遇到与手机之间相容性问题, 通常会用Frontline或Ellisys的Bluetooth Analyzer来截取资料分析, 如果手边没有这样的仪器, 要如何窥探Bluetooth的HCI log.这次介绍的是手机篇. 这次跟QCC518x/QCC308x测试的手机是Samsung S23 U…

【论文投稿】Python 网络爬虫:探秘网页数据抓取的奇妙世界

目录 前言 一、Python—— 网络爬虫的绝佳拍档 二、网络爬虫基础&#xff1a;揭开神秘面纱 &#xff08;一&#xff09;工作原理&#xff1a;步步为营的数据狩猎 &#xff08;二&#xff09;分类&#xff1a;各显神通的爬虫家族 三、Python 网络爬虫核心库深度剖析 &…

前端炫酷动画--图片(一)

目录 一、四角线框的跟随移动 二、元素倒影(-webkit-box-reflect) 三、模特换装(maskblend) 四、元素平滑上升 五、无限视差滚动 六、判断鼠标进入方向(轮播方向) 七、环形旋转效果 八、黑白小球交替旋转 九、hover时圆形放大 十、画一棵随机树(canvas) 十一、代码雨…

STL--list(双向链表)

目录 一、list 对象创建 1、默认构造函数 2、初始化列表 3、迭代器 4、全0初始化 5、全值初始化 6、拷贝构造函数 二、list 赋值操作 1、赋值 2、assign&#xff08;迭代器1&#xff0c;迭代器2&#xff09; 3、assign&#xff08;初始化列表&#xff09; 4、assig…

【语言处理和机器学习】概述篇(基础小白入门篇)

前言 自学笔记&#xff0c;分享给语言学/语言教育学方向的&#xff0c;但对语言数据处理感兴趣但是尚未入门&#xff0c;却需要在论文中用到的小伙伴&#xff0c;欢迎大佬们补充或绕道。ps&#xff1a;本文不涉及公式讲解&#xff08;文科生小白友好体质&#xff09;&#xff…

小程序获取微信运动步数

1、用户点击按钮&#xff0c;在小程序中触发getuserinfo方法&#xff0c;获取用户信息 <scroll-view class"scrollarea" scroll-y type"list"><view class"container"><button bind:tap"getLogin">获取</button&…

C 语言雏启:擘画代码乾坤,谛观编程奥宇之初瞰

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。* 这一课主要是让大家初步了解C语言&#xff0c;了解我们的开发环境&#xff0c;main函数&#xff0c;库…

VSCode下EIDE插件开发STM32

VSCode下STM32开发环境搭建 本STM32教程使用vscode的EIDE插件的开发环境&#xff0c;完全免费&#xff0c;有管理代码文件的界面&#xff0c;不需要其它IDE。 视频教程见本人的 VSCodeEIDE开发STM32 安装EIDE插件 Embedded IDE 嵌入式IDE 这个插件可以帮我们管理代码文件&am…

Linux内核编程(二十一)USB驱动开发

一、驱动类型 USB 驱动开发主要分为两种&#xff1a;主机侧的驱动程序和设备侧的驱动程序。一般我们编写的都是主机侧的USB驱动程序。 主机侧驱动程序用于控制插入到主机中的 USB 设备&#xff0c;而设备侧驱动程序则负责控制 USB 设备如何与主机通信。由于设备侧驱动程序通常与…

论文笔记-arXiv2025-A survey about Cold Start Recommendation

论文笔记-arXiv2025-Cold-Start Recommendation towards the Era of Large Language Models: A Comprehensive Survey and Roadmap 面向大语言模型&#xff08;LLMs&#xff09;时代的冷启动推荐&#xff1a;全面调研与路线图1.引言2.前言3.内容特征3.1数据不完整学习3.1.1鲁棒…

C#使用WMI获取控制面板中安装的所有程序列表

C#使用WMI获取控制面板中安装的所有程序列表 WMI 全称Windows Management Instrumentation,Windows Management Instrumentation是Windows中用于提供共同的界面和对象模式以便访问有关操作系统、设备、应用程序和服务的管理信息。如果此服务被终止&#xff0c;多数基于 Windo…

风光并网对电网电能质量影响的matlab/simulink仿真建模

这个课题早在一几年的时候比较热门&#xff0c;之前作电科院配电网的一个项目中也有所涉及&#xff0c;我把其中一部分经典仿真模型思路分享给大家&#xff0c;电能质量影响这部分&#xff0c;我在模型中主要体现的就是不同容量的光伏、风电接入&#xff0c;对并网点的电压影响…

.Net Core微服务入门全纪录(六)——EventBus-事件总线

系列文章目录 1、.Net Core微服务入门系列&#xff08;一&#xff09;——项目搭建 2、.Net Core微服务入门全纪录&#xff08;二&#xff09;——Consul-服务注册与发现&#xff08;上&#xff09; 3、.Net Core微服务入门全纪录&#xff08;三&#xff09;——Consul-服务注…

C#防止重复提交

C#防止重复提交 文章目录 C#防止重复提交前言防止重复提交的思路Web API 防止重复提交代码实现代码讲解使用方法 MVC防止重复提交总结 前言 当用户在前端进行提交数据时&#xff0c;如果网络出现卡顿和前端没有给出响应的话顾客通常都会狂点提交按钮&#xff0c;这样就很容易导…

python学opencv|读取图像(三十九 )阈值处理Otsu方法

【1】引言 前序学习了5种阈值处理方法&#xff0c;包括(反)阈值处理、(反)零值处理和截断处理&#xff0c;还学习了一种自适应处理方法&#xff0c;相关文章链接为&#xff1a; python学opencv|读取图像&#xff08;三十三&#xff09;阈值处理-灰度图像-CSDN博客 python学o…

嵌入式硬件篇---PID控制

文章目录 前言第一部分&#xff1a;连续PID1.比例&#xff08;Proportional&#xff0c;P&#xff09;控制2.积分&#xff08;Integral&#xff0c;I&#xff09;控制3.微分&#xff08;Derivative&#xff0c;D&#xff09;控制4.PID的工作原理5..实质6.分析7.各种PID控制器P控…

日志收集Day001

1.ElasticSearch 作用&#xff1a;日志存储和检索 2.单点部署Elasticsearch与基础配置 rpm -ivh elasticsearch-7.17.5-x86_64.rpm 查看配置文件yy /etc/elasticsearch/elasticsearch.yml&#xff08;这里yy做了别名&#xff0c;过滤掉空行和注释行&#xff09; yy /etc/el…

《offer 来了:Java 面试核心知识点精讲 -- 框架篇》(附资源)

继上篇文章介绍了《offer 来了&#xff1a;Java 面试核心知识点精讲 -- 原理篇》书后&#xff0c;本文章再给大家推荐兄弟篇 《offer来了&#xff1a;Java面试核心知识点精讲--框架篇》&#xff0c; 简直就是为Java开发者量身定制的面试神器。 本书是对Java程序员面试中常见的…