全新揭秘: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
    @Bean
    public 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事件,接收客户端请求,建立连接
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        System.out.println("客户端:" + userId + "建立连接");
        clientMap.put(userId, session);
    }

    /**
     * 用来处理客户端发送消息事件,接收消息并处理
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public 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
     */
    @OnClose
    public 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,实际业务场景可以用当前登录的用户的唯一标识

    //判断当前浏览器是否支持WebSocket
    if('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应用,在实时性、低延迟和全双工这些方面,将会非常高效。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数字图像处理】实验四 图像分割

一、实验内容&#xff1a; 1&#xff0e; 熟悉和掌握利用Matlab工具进行数字图像的读、写、显示等数字图像处理基本步骤。 2&#xff0e; 熟练掌握各种图像分割的基本原理及方法。 3&#xff0e; 能够从深刻理解图像分割&#xff0c;并能够思考拓展到一定的应用领域。 二、实验…

GraphPad Prism 10 for Mac v10.0.0.3 安装教程

GraphPad Prism GraphPad Prism是一款非常专业强大的科研医学生物数据处理绘图软件&#xff0c;它可以将科学图形、综合曲线拟合&#xff08;非线性回归&#xff09;、可理解的统计数据、数据组织结合在一起&#xff0c;除了最基本的数据统计分析外&#xff0c;还能自动生成统…

ARM GIC(四) gicv3架构基础

GICv3架构是GICv2架构的升级版&#xff0c;增加了很多东西。变化在于以下&#xff1a; 使用属性层次&#xff08;affinity hierarchies&#xff09;&#xff0c;来对core进行标识&#xff0c;使gic支持更多的core 将cpu interface独立出来&#xff0c;用户可以将其设计在core…

安卓好用的python编辑器,安卓平台python编辑器

本篇文章给大家谈谈安卓上好用的python编辑软件有哪些&#xff0c;以及安卓上好用的python编辑软件推荐&#xff0c;希望对各位有所帮助&#xff0c;不要忘了收藏本站喔。 1. 简介 Thonny是基于python内置图形库tkinter开发出来的支持多平台(windows,Mac,Linux)的python IDE&am…

Windows10操作系统上安装VMware虚拟机和CentOS7

最初使用Windows与CentOS双系统&#xff0c;发现在系统之间切换非常不方便&#xff0c;于是决定改用windows系统加虚拟机的方式。 我百度搜索下载的VMware Workstation 12 pro&#xff0c;下载地址&#xff1a;https://www.zdfans.com/html/23471.html&#xff0c;网页提供了序…

【Hadoop】YARN简介(YARN产生的技术需求/YARN的基本架构)

YARN产生的技术需求YARN的基本架构ResourceManagerNodeManagerApplicationMasterContainer HDFS与YARN YARN产生的技术需求 YARN是Hadoop v2.0 引入的核心组件。YARN 从某种那个意义上来说应该算做是一个云操作系统&#xff0c;它负责集群的资源管理和任务调度&#xff0c;在 …

机器学习:手撕 AlphaGo(一)

图 1-1: AphaGo 结构概览 1. 前言 AlphaGo 是一个非常经典的模型&#xff0c;不论从影响力还是模型设计上。它的技术迭代演进路径&#xff1a;AlphaGo&#xff0c;AlphaGoZero&#xff0c;AlphaZero&#xff0c;MuZero 更是十分精彩。相信有很多同学因为听了 AlphaGo 的故事对…

伽马校正:FPGA

参考资料&#xff1a; Tone Mapping 与 Gamma Correction - 知乎 (zhihu.com) Book_VIP: 《基于MATLAB与FPGA的图像处理教程》此书是业内第一本基于MATLAB与FPGA的图像处理教程&#xff0c;第一本真正结合理论及算法加速方案&#xff0c;在Matlab验证&#xff0c;以及在FPGA上…

CSS(五) -- 动效实现(立体盒子旋转-四方体+正六边)

一. 四面立体旋转 正方形旋转 小程序中 wxss中 <!-- 背景 --><view class"dragon"><!--旋转物体位置--><view class"dragon-position"><!--旋转 加透视 有立体的感觉--><view class"d-parent"><view …

【JVM】一、认识JVM

文章目录 1、虚拟机2、Java虚拟机3、JVM的整体结构4、Java代码的执行流程5、JVM的分类6、JVM的生命周期 1、虚拟机 虚拟机&#xff0c;Virtual Machine&#xff0c;一台虚拟的计算机&#xff0c;用来执行虚拟计算机指令。分为&#xff1a; 系统虚拟机&#xff1a;如VMware&am…

Bash 脚本学习

文章目录 1、脚本编程基础2. 变量2.1 参数变量的引用2.2 环境变量 3 条件判断语句3.1 if 语句3.1.1 语法3.1.2 案例 3.2 case 语句3.2.1 语法3.2.2 案例 3.3 判断参数说明 4 循环语句4.1 for 循环4.1.1 语法4.1.2 案例 4.2 while循环4.2.1 语法4.2.2 案例4. 3 循环总结 5. 函数…

7.串口通信uart编写思路及自定义协议

前言&#xff1a; 串口是很重要的&#xff0c;有许多模块通信接口就是串口&#xff0c;例如gps模块&#xff0c;蓝牙模块&#xff0c;wifi模块还有一些精度比较高的陀螺仪模块等等&#xff0c;所以学会了串口之后&#xff0c;这些听起来很牛批的模块都能够用起来了。此外&#…

RTP/RTCP/RTSP/SIP/SDP/RTMP对比

RTP&#xff08;Real-time Transport Protocol&#xff09;是一种用于实时传输音频和视频数据的协议。它位于传输层和应用层之间&#xff0c;主要负责对媒体数据进行分包、传输和定时。 RTCP&#xff08;Real-Time Control Protocol&#xff09;是 RTP 的控制协议&#xff0c;…

持续集成交付CICD:基于ArgoCD 的GitOps 自动化完成前端项目应用发布与回滚

目录 一、实验 1. 环境 2. K8S master节点部署Argo CD 3.基于ArgoCD 实现GitOps &#xff08;同步部署文件&#xff09; 4.基于ArgoCD 实现GitOps &#xff08;同步HELM文件&#xff09; 二、问题 1. ArgoCD 连接K8S集群状态为 Unknown 2.ArgoCD 创建application失败 …

03-JVM对象创建与内存分配机制深度剖析

文章目录 对象的创建对象创建的主要流程一、类加载检查二、分配内存划分内存的方法解决并发问题的方法 三、初始化零值四、设置对象头五、执行<init>方法 对象半初始化对象大小与指针压缩什么是java对象的指针压缩&#xff1f;为什么要进行指针压缩&#xff1f; 对象内存…

快速学习 webpack

目录 1. webpack基本概念 webpack能做什么&#xff1f; 2. webpack的使用步骤 2.1_webpack 更新打包 3. webpack的配置 3.1_打包流程图 3.2_案例-webpack隔行变色 3.3_插件-自动生成html文件 3.4_加载器 - 处理css文件问题 3.5_加载器 - 处理css文件 3.6_加载器 - 处…

【深入解析spring cloud gateway】12 gateway参数调优与分析

本节主要对网关主要的一些参数做一些解释说明&#xff0c;并用压测工具测试一下网关的接口&#xff0c;通过压测来验证参数配置是否合理 一、连接池参数 参数示例 spring:application:name: gatewaycloud:gateway:# http连接设置httpclient:# 全局的响应超时时间&#xff0c…

驱动开发的完善 --- 芯片手册导读 + I/O口操控代码的编写

在我上上节的博文中&#xff08;linux驱动的学习 & 驱动开发初识-CSDN博客&#xff09;&#xff1a; 我通过一个基本的字符设备驱动框架来测试了驱动的运行&#xff0c;但是在“pin4_open”和“pin4_write”这两个驱动函数的函数体里只写了一句内核打印的代码&#xff0c;作…

微软官方出品:GPT大模型编排工具,支持C#、Python等多个语言版本

随着ChatGPT的火热&#xff0c;基于大模型开发应用已经成为新的风口。虽然目前的大型模型已经具备相当高的智能水平&#xff0c;但它们仍然无法完全实现业务流程的自动化&#xff0c;从而达到用户的目标。 微软官方开源的Semantic Kernel的AI编排工具&#xff0c;就可以很好的…

【深度学习】注意力机制(七)Agent Attention

本文介绍Agent Attention注意力机制&#xff0c;Transformer中的Attention模块可以提取全局语义信息&#xff0c;但是计算量太大&#xff0c;Agent Attention是一种计算非常有效的Attention模块。 论文&#xff1a;Agent Attention: On the Integration of Softmax and Linear…