【技术】Web实时消息推送方式整理

news2024/11/19 1:41:03

【技术】Web实时消息推送方式整理


SSE 单向 服务器 --> 客户端

text/event-stream类型的数据流信息

实现

客户端

<script>
    let source = null;
    let userId = 7777
    if (window.EventSource) {
        // 建立连接
        source = new EventSource('http://localhost:7777/sse/sub/'+userId);
        setMessageInnerHTML("连接用户=" + userId);
        /**
         * 连接一旦建立,就会触发open事件
         * 另一种写法:source.onopen = function (event) {}
         */
        source.addEventListener('open', function (e) {
            setMessageInnerHTML("建立连接。。。");
        }, false);
        /**
         * 客户端收到服务器发来的数据
         * 另一种写法:source.onmessage = function (event) {}
         */
        source.addEventListener('message', function (e) {
            setMessageInnerHTML(e.data);
        });
    } else {
        setMessageInnerHTML("你的浏览器不支持SSE");
    }
</script>

服务端

private static Map<String, SseEmitter> sseEmitterMap = new ConcurrentHashMap<>();

/**
 * 创建连接
 *
 */
public static SseEmitter connect(String userId) {
    try {
        // 设置超时时间,0表示不过期。默认30秒
        SseEmitter sseEmitter = new SseEmitter(0L);
        // 注册回调
        sseEmitter.onCompletion(completionCallBack(userId));
        sseEmitter.onError(errorCallBack(userId));
        sseEmitter.onTimeout(timeoutCallBack(userId));
        sseEmitterMap.put(userId, sseEmitter);
        count.getAndIncrement();
        return sseEmitter;
    } catch (Exception e) {
        log.info("创建新的sse连接异常,当前用户:{}", userId);
    }
    return null;
}

/**
 * 给指定用户发送消息
 *
 */
public static void sendMessage(String userId, String message) {

    if (sseEmitterMap.containsKey(userId)) {
        try {
            sseEmitterMap.get(userId).send(message);
        } catch (IOException e) {
            log.error("用户[{}]推送异常:{}", userId, e.getMessage());
            removeUser(userId);
        }
    }
}


WebSocket 双向    服务端 <--> 客户端

实现

客户端

<script>
    var ws = new WebSocket('ws://localhost:7777/webSocket/10086');
    // 获取连接状态
    console.log('ws连接状态:' + ws.readyState);
    //监听是否连接成功
    ws.onopen = function () {
        console.log('ws连接状态:' + ws.readyState);
        //连接成功则发送一个数据
        ws.send('test1');
    }
    // 接听服务器发回的信息并处理展示
    ws.onmessage = function (data) {
        console.log('接收到来自服务器的消息:');
        console.log(data);
        //完成通信后关闭WebSocket连接
        ws.close();
    }
    // 监听连接关闭事件
    ws.onclose = function () {
        // 监听整个过程中websocket的状态
        console.log('ws连接状态:' + ws.readyState);
    }
    // 监听并处理error事件
    ws.onerror = function (error) {
        console.log(error);
    }
    function sendMessage() {
        var content = $("#message").val();
        $.ajax({
            url: '/socket/publish?userId=10086&message=' + content,
            type: 'GET',
            data: { "id": "7777", "content": content },
            success: function (data) {
                console.log(data)
            }
        })
    }
</script>

服务端

@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")
public class WebSocketServer {
    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    private static final CopyOnWriteArraySet<WebSocketServer> webSockets = new CopyOnWriteArraySet<>();
    // 用来存在线连接数
    private static final Map<String, Session> sessionPool = new HashMap<String, Session>();
    /**
     * 链接成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "userId") String userId) {
        try {
            this.session = session;
            webSockets.add(this);
            sessionPool.put(userId, session);
            log.info("websocket消息: 有新的连接,总数为:" + webSockets.size());
        } catch (Exception e) {
        }
    }
    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void onMessage(String message) {
        log.info("websocket消息: 收到客户端消息:" + message);
    }
    /**
     * 此为单点消息
     */
    public void sendOneMessage(String userId, String message) {
        Session session = sessionPool.get(userId);
        if (session != null && session.isOpen()) {
            try {
                log.info("websocket消: 单点消息:" + message);
                session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

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

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

相关文章

DC电源模块关于多路输出的问题

BOSHIDA DC电源模块关于多路输出的问题 DC电源模块通常具备多路输出功能&#xff0c;这使得它在实际应用中具有极高的灵活性和可扩展性。当需要为多个不同的负载提供电源时&#xff0c;多路输出的设计可以降低整个系统的成本和复杂度&#xff0c;同时也可以减少系统空间的占用。…

docker菜谱大全

记录docker常用软件安装&#xff0c;欢迎大家投稿。&#x1f60e;&#x1f60e;&#x1f60e; 相关文档&#xff1a; DockerHub&#xff1a;https://hub.docker.com/Linux手册&#xff1a;https://linuxcool.com/Docker文档&#xff1a;https://docs.docker.com/Docker中文网&a…

Java加密算法的应用与实现(MD5、SHA、DES、3DES、AES、RSA、ECC)

文章目录 一、散列加密算法1、概述2、常见算法&#xff08;MD5、SHA&#xff09;3、应用4、Java实现 二、对称加密算法1、概述2、常见算法&#xff08;DES、3DES、AES&#xff09;3、应用4、Java实现AES 三、非对称加密算法1、概述2、常见算法&#xff08;RSA、ElGamal、Rabin、…

C++数学知识模板

试除法判定质数 模板 bool check_primes(int x) {for(int i 2; i * i < x; i) {if(x % i 0) return false;}return true; } 模板题 866. 试除法判定质数 给定 n个正整数 ai&#xff0c;判定每个数是否是质数。 输入格式 第一行包含整数 n。 接下来 n行&#xff0c…

试卷怎么去笔记和答案?这个工具好好用起来

在做试卷的过程中&#xff0c;整理笔记和答案是非常重要的&#xff0c;我们通常都会有一张用来写解题思路的草稿纸&#xff0c;这样可以避免直接在试卷上解答发现思路不对但也不能修改的困难了。但有时候我们写作业时难免会在试卷上解答出错&#xff0c;面对这种问题伙伴们其实…

第一百二十四天学习记录:C++提高:STL-deque容器(上)(黑马教学视频)

deque容器 deque容器基本概念 功能&#xff1a; 双端数组&#xff0c;可以对头端进行插入删除操作 deque与vector区别 vector对于头部的插入删除效率低&#xff0c;数据量越大&#xff0c;效率越低 deque相对而言&#xff0c;对头部的插入删除速度比vector快 vector访问元素的…

十九、docker学习-Dockerfile

Dockerfile 官网地址 https://docs.docker.com/engine/reference/builder/Dockerfile其实就是我们用来构建Docker镜像的源码&#xff0c;当然这不是所谓的编程源码&#xff0c;而是一些命令的集合&#xff0c;只要理解它的逻辑和语法格式&#xff0c;就可以很容易的编写Docke…

C数据结构与算法——二叉树 应用一

实验任务 (1) 掌握二叉树的二叉链表存储结构定义&#xff1b; (2) 掌握该存储方式下的二叉树基本算法&#xff1b; (3) 掌握三种遍历的递归算法。 实验内容 实现二叉链表存储结构及其基本算法算法简单应用 创建一颗二叉树的二叉链表输出该二叉树的三种遍历序列&#xff08;前…

redis的事务和watch机制

这里写目录标题 第一章、redis事务和watch机制1.1&#xff09;redis事务&#xff0c;事务的三大命令语法&#xff1a;开启事务 multi语法&#xff1a;执行事务 exec语法&#xff1a;取消事务 discard 1.2&#xff09;redis事务的错误和回滚的情况1.3&#xff09;watch机制语法&…

NodeJS 个性化音乐推荐系统 毕业设-附源码00485

摘要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#xff0c;应用软件的工作规…

在excel调用SAP函数执行SAP数据查找或提交

1、下载插件 2、安装插件 3、执行函数 3.1 第一步 通过SAPRegister连接SAP服务器 var reg SAPRegister("10.10.14.15", "00", "mes", "AQ123456", "800") 需要改为实际的连接信息 "10.10.14.15" 为SAP服务器I…

【如何构建自己的基于Arduino的Scara 机器人】

【如何构建自己的基于Arduino的Scara 机器人】 1. 概述2. Scara机器人3D模型3. 3D打印机器人零件4. 组装机器人5. SCARA机器人电路图6. 完成装配7. SCARA机器人的工作原理8. 对 SCARA 机器人进行编程 – Arduino 和处理代码9. 总结在本教程中,我们将学习如何构建基于 Arduino …

Linux下C语言调用libcurl库下载文件到本地

一、项目介绍 当前文章介绍如何使用C语言调用libcurl库在Linux&#xff08;Ubuntu&#xff09;操作系统下实现网络文件下载功能。 libcurl是一个开源的跨平台网络传输库&#xff0c;用于在C和C等编程语言中实现各种网络通信协议的客户端功能。它支持多种协议&#xff0c;包括…

监测冷却塔面临的挑战和解决方案

工业冷却塔是现代生产过程中不可或缺的一部分&#xff0c;其稳定高效的运行对于许多工业流程至关重要。然而&#xff0c;冷却塔的监测任务并非易事&#xff0c;因为它们既有许多与其他旋转设备相似的特征&#xff0c;又面临一系列独特的挑战。在本文中&#xff0c;我们将探讨监…

在qemu中挂载镜像文件

将镜像文件作为交换分区 创建镜像文件&#xff1a; dd if/dev/zero ofswap.img bs512 count131072 qemu-system-arm -nographic -M vexpress-a9 -m 64M -kernel arch/arm/boot/zImage -append "rdinit/linuxrc consolettyAMA0 loglevel8" -dtb arch/arm/boot/dts/…

使用Automatic1111在本地PC上运行SDXL 1.0

这是我们部署Stable Diffusion的第三篇文章了&#xff0c;前两篇文章都详细介绍了Automatic1111的stable-diffusion-webui的安装&#xff0c;这次主要介绍如何使用SDXL 1.0模型。 获取项目 在本地获取Automatic1111’s WebUI项目&#xff0c;下载完成后应该是这个样子的 下载检…

【Redis】使用Docker镜像配置集群时的Operation timed out问题

不知道有没有小伙伴跟我一样是使用的Docker镜像进行Redis集群案例模拟的&#xff08;三台虚拟机确实带不动 &#xff09;&#xff0c;然后我遇到了一个问题&#xff1a;Could not connect to Redis at 172.17.0.2:6379: Operation timed out 172.17.0.2是我其中一个Redis实例的…

解决域控转移5个角色后关掉原主域控无法使用

最近域控win2016要升级到win2022&#xff0c;每次都是角色转移了&#xff0c;但是原先域控断网后&#xff0c;新角色域控无法单独运行&#xff0c;会提示找不到域服务器之类的 //转移5大角色 //需要在powershell执行 Move-ADDirectoryServerOperationMasterRole -Identity 你的…

Electron+vue3项目使用SQLite3数据库

SQLite 是一个进程内的库&#xff0c;实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库&#xff0c;这意味着与其他数据库不一样&#xff0c;我们不需要在系统中配置。 就像其他数据库&#xff0c;SQLite 引擎不是一个独立的进程&am…

C#,数值计算——多维下坡单纯形法(Downhill Simplex Method in Multidimensions)的计算方法与源程序

using System; namespace Legalsoft.Truffer { /// <summary> /// 多维下坡单纯形法 /// Downhill Simplex Method in Multidimensions /// </summary> public class Amoeba { private int nfunc { get; set; } private …