全新揭秘:Java WebSocket全双工通信的实践与运用

全新揭秘:Java WebSocket全双工通信的实践与运用

    • 一、简介
      • 何为全双工通信全双工?
      • WebSocket的使用场景
    • 二、如何使用Java实现WebSocket
      • 1,引用websocket相关starter
      • 2,启用websocket
      • 3,服务端代码开发
      • 4,群发测试接口
      • 5,前端代码
    • 三、测试验证
    • 四、总结

一、简介

WebSocket是一种强大的跨平台和全双工通信的网络技术。它可以在客户端和服务器之间进行全双工通信,从而在真实的服务器推送场景中提供极好的性能和一致性。

何为全双工通信全双工?

全双工模式是指两端系统可以同时发送和接收信息,即客户端可以向服务端发起请求,并接收服务端的响应, 同时,服务端也可以主动向客户端发起请求,并接收客户端的响应。 而我们最常见的web应用,都属于请求-响应,属于半双工模式, 这种模式下,服务端是不能主动请求客户端的。
WebSocket提供了这种全双工通信方式,使得服务器可以随时把信息推送给客户端,客户端也能随时向服务器发送信息,减少了通信的延迟时间。

WebSocket的使用场景

这种全双工的通信方式,使得WebSocket在一些特殊场景下有着无比的优势:
1,实时应用:聊天室应用,多人协作的应用。
2,游戏应用:浏览器游戏或者手机app游戏等,他们需要在服务端和客户端之间保持低延迟、全双工和实时的数据交换。
3,实时展现:对于需要频繁更新的应用,WebSocket提供了一种高效的解决方案。
以及无需客户端提供公网IP,服务端即可以访问客户端的某些特殊场景(B2B场景下),比如服务端对接了多家银行,支付时又依赖于客户端插入的U盾。

二、如何使用Java实现WebSocket

Java EE7的APIs支持WebSocket协议,因此我们使用Java来实现WebSocket变得非常简单。以下以一个springboot web应用中,使用java WebSocket进行全双工通信示例:

1,引用websocket相关starter

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

2,启用websocket

在springboot启动类中,增加如下代码:

// 启用websocket@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}

3,服务端代码开发

import org.springframework.stereotype.Component;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;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;/*** WebSocket测试服务*/
@Component  // 也需要交于spring容器管理
@ServerEndpoint("/ws/{userId}")  // 服务地址
public class TestWebSocketServer {//长连接,即客户端会话对象private static Map<String, Session> clientMap = new HashMap();/*** 响应客户端socket open事件,接收客户端请求,建立连接*/@OnOpenpublic void onOpen(Session session, @PathParam("userId") String userId) {System.out.println("客户端:" + userId + "建立连接");clientMap.put(userId, session);}/*** 用来处理客户端发送消息事件,接收消息并处理** @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, @PathParam("userId") String userId) throws IOException {System.out.println("收到来自客户端:" + userId + "的信息:" + message);Session session = clientMap.get(userId);session.getBasicRemote().sendText(userId + " 你好,已收到你发送的消息:" + message);}/*** 响应客户端连接关闭事件调用的方法** @param userId*/@OnClosepublic void onClose(@PathParam("userId") String userId) {System.out.println("连接断开:" + userId);clientMap.remove(userId);}/*** 测试群发消息,实现业务场景根据业务需要,发给特定的客户端,以实现客户端无刷新自动显示最新数据,比如下单被接单,客户催单提醒等。** @param message*/public void sendMessagesToALlUsers(String message) {Collection<Session> sessions = clientMap.values();for (Session session : sessions) {try {//服务器向客户端发送消息session.getBasicRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}}

4,群发测试接口

    @GetMapping("/ws/sendAll")public String sendToAllClients() {testWebSocketServer.sendMessagesToALlUsers("群发消息测试");return "success";}

5,前端代码

创建一个html页面,命名ws_demo.html,代码如下:

<!DOCTYPE HTML>
<html>
<head><meta charset="UTF-8"><title>WebSocket Demo</title>
</head>
<body><input id="text" type="text" /><button onclick="send()">发送消息</button><button onclick="closeWebSocket()">断开连接</button><div id="message"></div>
</body>
<script type="text/javascript">var websocket = null;var clientId = "10000";  //  模拟的用户ID,实际业务场景可以用当前登录的用户的唯一标识//判断当前浏览器是否支持WebSocketif('WebSocket' in window){//连接WebSocket节点websocket = new WebSocket("ws://localhost:9600/ws/"+clientId);}else{alert('Not support websocket')}//连接发生错误前端回调方法,比如服务端挂了websocket.onerror = function(){setMessageInnerHTML("与服务端连接出错");};//连接成功建立的回调方法websocket.onopen = function(){setMessageInnerHTML("与服务端建立连接成功");}//接收到消息的回调方法websocket.onmessage = function(event){setMessageInnerHTML(event.data);}//连接关闭的回调方法websocket.onclose = function(){setMessageInnerHTML("已关闭");}//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。window.onbeforeunload = function(){closeWebSocket();}//将消息显示在网页上function setMessageInnerHTML(innerHTML){document.getElementById('message').innerHTML += innerHTML + '<br/>';}//发送消息function send(){var message = document.getElementById('text').value;websocket.send(message);}//关闭连接function closeWebSocket() {websocket.close();}
</script>
</html>

三、测试验证

springboot后端应用启动:
在这里插入图片描述
打开前端页面
前端如果打开后,不能正常显示 ,可以将前端部署在nginx上,直接放到nginx的html目录下即可,然后通过浏览器访问http://localhost/ws_demo.html 即可显示页面如下。
在这里插入图片描述
在这里插入图片描述
客户端主动发送消息

在这里插入图片描述
服务端收到客户端响应
在这里插入图片描述
服务端主动向客户端群发测试
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
客户端断开(浏览器关闭)时,会触发onclose事件,服务端也会感知到; 同时服务端关闭时,也会触发服务端onclose事件,客户端也会被通知到,大家可以测试验证下。
以上测试展示了一个基于java websocket的全双工网络通信的具体示例,实现客户端和服务器之间进行全双工通信非常简便,在真实的服务器推送场景中只需扩展示例,实现具体的业务即可。

四、总结

总的来看,WebSocket带来了客户端和服务端通信的新可能,特别是在需要服务端主动推送消息给客户端的应用场景中,其出色的实时性和低延迟性提供了前所未有的用户体验。Java作为一门全能的编程语言,也为我们使用WebSocket提供了完善的工具。使用Java去实现WebSocket应用,在实时性、低延迟和全双工这些方面,将会非常高效。

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

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

相关文章

GitHub打不开或者访问慢解决方法

一、获取IP地址 首先进入下面的网站 IP/DNS Detect 获取到当前github.com对应的IP地址 可以多search几次, github.com对应的IP地址不止一个,都记录下来 二、修改hosts文件内容 找到文件夹路径&#xff1a;C:\Windows\System32\drivers\etc\ 打开hosts文件&#xff0c;将刚才…

VLOOKUP中的#N/A错误很常见,这里有详细排除步骤

你的VLOOKUP是否提取了错误的数据&#xff0c;或者你根本无法使其工作&#xff1f;本教程展示了如何快速修复常见的VLOOKUP中的#N/A错误并克服其主要限制。 ​在VLOOKUP公式中&#xff0c;当Excel找不到查找值时&#xff0c;会显示#N/A错误消息&#xff08;意思是“不可用”&a…

@vue/cli脚手架

0_vue/cli 脚手架介绍 目标: webpack自己配置环境很麻烦, 下载vue/cli包,用vue命令创建脚手架项目 vue/cli是Vue官方提供的一个全局模块包(得到vue命令), 此包用于创建脚手架项目 脚手架是为了保证各施工过程顺利进行而搭设的工作平 vue/cli的好处 开箱即用 0配置webpack babe…

全自动双轴晶圆划片机:半导体制造的关键利器

随着科技的飞速发展&#xff0c;半导体行业正以前所未有的速度向前迈进。在这个过程中&#xff0c;全自动双轴晶圆划片机作为一种重要的设备&#xff0c;在半导体晶圆、集成电路、QFN、发光二极管、miniLED、太阳能电池、电子基片等材料的划切过程中发挥着举足轻重的作用。 全自…

selenium 报错

selenium 报错 开始学自动化测试&#xff0c;&#xff0c;环境配了一天TAT 安装好selenium之后 运行python脚本 # codingutf-8 from selenium import webdriver import timedriver webdriver.Chrome() driver.get("https://www.baidu.com") time.sleep(3) driver.…

Unity 物体高亮插件 Highlighting System 使用

效果图 下载链接 链接&#xff1a;https://pan.baidu.com/s/1ojCibjIt6FpBej6KRw3mtw 提取码&#xff1a;nngq 使用简介 导入插件 HighlightingSystemEditor.cs&#xff1a;脚本用来控制高亮插件的渲染。 HighlightableObject.cs&#xff1a;挂载到需要高亮的物体 Highlighti…

目标检测入门体验,技术选型,加载数据集、构建机器学习模型、训练并评估

Hi, I’m Shendi 1、目标检测入门体验&#xff0c;技术选型&#xff0c;加载数据集、构建机器学习模型、训练并评估 在最近有了个物体识别的需求&#xff0c;于是开始学习 在一番比较与询问后&#xff0c;最终选择 TensorFlow。 对于编程语言&#xff0c;我比较偏向Java或nod…

C#上位机与欧姆龙PLC的通信04---- 欧姆龙plc的存储区

1、存储区概念 欧姆龙PLC将整个数据存储器分为10个区&#xff1a;输入继电器区、输出继电器区、内部辅助继电器区、特殊继电器区、保持继电器区、暂存继电器区、定时/计数器区、数据存储区、辅助存储继电器区、链接继电器区。 输入输出继电器区 CP1E系列PLC输入继电器区有16…

Docker 文件和卷 权限拒绝

一 创作背景 再复制Docker影像文件或访问Docker容器内已安装卷上的文件时我们常常会遇到&#xff1a;“权限被拒绝”的错误&#xff0c;在此&#xff0c;您将了解到为什么会出现“权限被拒绝”的错误以及如何解决这个问题。 二 目的 在深入探讨 Docker 容器中的 Permission De…

SpringCloudGateway网关处拦截并修改请求

SpringCloudGateway网关处拦截并修改请求 需求背景 老系统没有引入Token的概念&#xff0c;之前的租户Id拼接在请求上&#xff0c;有的是以Get&#xff0c;Param传参形式&#xff1b;有的是以Post&#xff0c;Body传参的。需要在网关层拦截请求并进行请求修改后转发到对应服务。…

​ SK Ecoplant借助亚马逊云科技,海外服务器为环保事业注入新活力

在当今全球面临着资源紧缺和环境挑战的大背景下&#xff0c;数字技术所依赖的海外服务器正成为加速循环经济转型的关键利器。然而&#xff0c;很多企业在整合数字技术到运营中仍然面临着一系列挑战&#xff0c;依然存在低效流程导致的不必要浪费。针对这一问题&#xff0c;SK E…

工具系列:PyCaret介绍_用外生变量单变量时间序列预测

工具系列&#xff1a;PyCaret介绍_用外生变量单变量时间序列预测 在这组笔记本中&#xff0c;我们将介绍使用外生变量进行建模。我们的行动计划如下&#xff1a; 对数据集进行探索性数据分析&#xff0c;以提取关于生成时间序列的过程的有价值的见解。 构建一个基准模型&…