webSocket简单接收发送案例

ops/2024/10/31 22:31:12/

pom添加:

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

socket服务实现


import com.alibaba.fastjson.JSON;
import com.hdtd.safequalitycollect.common.utils.DateFormatterUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Component;import javax.websocket.OnClose;
import javax.websocket.OnError;
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.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;@Slf4j
@ServerEndpoint("/earlyWarning/{sid}")
@Component
public class EarlyWarningWebsocketServer {/*** concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。*/private static final CopyOnWriteArraySet<EarlyWarningWebsocketServer> webSocketSet = new CopyOnWriteArraySet<>();/*** 忽略预警消息列表* key:用户id+时间戳,value:预警类型*/private static final HashMap<String,String> warningIgnoreList = new HashMap<>();/*** 与某个客户端的连接会话,需要通过它来给客户端发送数据*/private Session session;/*** 设置websocket超时时间*/public static final long MAX_TIME_OUT = 50L * 60L * 1000L;/*** 接收sid*/private String sid = "";/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam("sid") String sid) {this.session = session;session.setMaxIdleTimeout(MAX_TIME_OUT);//如果存在就先删除一个,防止重复推送消息for (EarlyWarningWebsocketServer webSocket : webSocketSet) {if (webSocket.sid.equals(sid)) {webSocketSet.remove(webSocket);}}this.sid = sid;webSocketSet.add(this);}/*** 连接关闭调用的方法*/@OnClosepublic void onClose() {webSocketSet.remove(this);}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, Session session) {log.info("收到来自" + sid + "的信息:" + message);//群发消息
//        String yyMmDdHh = DateFormatterUtils.getYyMmDdHh();
//        if(ObjectUtils.isEmpty(warningIgnoreList.get(sid + yyMmDdHh))){
//            // 清空warningIgnoreList中,key包含 sid 的,并且预警类型与message相同的记录
//            Iterator<String> iterator = warningIgnoreList.keySet().iterator();
//            while (iterator.hasNext()) {
//                String key = iterator.next();
//                if (key.contains(sid) && Objects.equals(warningIgnoreList.get(key), message)) {
//                    iterator.remove();
//                }
//            }
//            warningIgnoreList.put(sid + yyMmDdHh, message);
//        }}@OnErrorpublic void onError(Session session, Throwable error) {log.error(session.getId() + "发生错误");error.printStackTrace();}/*** 实现服务器主动推送*/public void sendMessage(String message) throws IOException {synchronized (session) {this.session.getBasicRemote().sendText(message);log.info("推送消息到" + sid + "成功,消息为:" + message);}}/*** 群发自定义消息*/public static void sendInfo(String message) {for (EarlyWarningWebsocketServer productWebSocket : webSocketSet) {try {productWebSocket.sendMessage(message);log.info("推送消息给全体用户" + "成功,消息为:" + message);} catch (Exception e) {log.error("推送消息失败:{}", e.getMessage());}}}/*** 给指定连接用户自定义消息*/public static void sendInfo(SocketMsg socketMsg, @PathParam("sid") String sid) throws IOException {String message = JSON.toJSONString(socketMsg);log.info("推送消息到" + sid + ",推送内容:" + message);for (EarlyWarningWebsocketServer item : webSocketSet) {try {//这里可以设定只推送给这个sid的,为null则全部推送if (sid == null || item.sid.equals(sid)) {item.sendMessage(message);}} catch (IOException ignored) {log.error("消息推送失败:{}", ignored.getMessage());}}}/*** 给特定客户端发送信息*/public static void sendInfo(String message, String sid) throws IOException {log.info("推送消息到" + sid + ",推送内容:" + message);for (EarlyWarningWebsocketServer item : webSocketSet) {try {//这里可以设定只推送给这个sid的,为null则全部推送if (sid == null || item.sid.equals(sid)) {item.sendMessage(message);}} catch (IOException ignored) {log.error("消息推送失败:{}", ignored.getMessage());}}}@Overridepublic boolean equals(Object o) {if (this == o) {return true;}if (o == null || getClass() != o.getClass()) {return false;}EarlyWarningWebsocketServer that = (EarlyWarningWebsocketServer) o;return Objects.equals(session, that.session) &&Objects.equals(sid, that.sid);}@Overridepublic int hashCode() {return Objects.hash(session, sid);}}

项目启动后,socket服务自动启动

前端案例:

<!DOCTYPE HTML>
<html>
<head><title>WebSocket</title>
</head><body>
Welcome<br/>
<input id="text" type="text" />
<button onclick="send()">Send</button>
<button onclick="closeWebSocket()">Close</button>
<div id="message">
</div>
</body><script type="text/javascript">var websocket = null;//判断当前浏览器是否支持WebSocketif('WebSocket' in window){websocket = new WebSocket("ws://XXX:8080/earlyWarning/2");}else{alert('Not support websocket')}//连接发生错误的回调方法websocket.onerror = function(){setMessageInnerHTML("error");};//连接成功建立的回调方法websocket.onopen = function(event){setMessageInnerHTML("open");}//接收到消息的回调方法websocket.onmessage = function(event){setMessageInnerHTML(event.data);}//连接关闭的回调方法websocket.onclose = function(){setMessageInnerHTML("close");}//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。window.onbeforeunload = function(){websocket.close();}//将消息显示在网页上function setMessageInnerHTML(innerHTML){document.getElementById('message').innerHTML += innerHTML + '<br/>';}//关闭连接function closeWebSocket(){websocket.close();}//发送消息function send(){var message = document.getElementById('text').value;websocket.send(message);}
</script>
</html>

实现效果:

后台发送消息到前端,前端页面进行处理,前端也可以发送对应信息给后台,后台处理。

注意:socket连接时,需要前端提供对应的用户id,对用户进行区分,可以实现单个用户的发送接收。


http://www.ppmy.cn/ops/129954.html

相关文章

【Qt】系统相关——多线程、Qt多线程介绍、常用函数、线程安全、网络、UDP Socket、TCP Socket

文章目录 Qt系统相关1. 多线程1.1 Qt多线程介绍1.2 常用函数1.3 线程安全 2. 网络2.1 UDP Socket2.2 TCP Socket Qt 系统相关 1. 多线程 1.1 Qt多线程介绍 QThread 代表一个在应用程序中可以独立控制的线程&#xff0c;它还可以和进程中的其他线程共享数据。QThread 对象管理…

无人机避障——路径规划篇(一) JPS跳点搜索算法A*算法对比

JSP 跳点搜索算法与改进 A*算法对比 一、算法概述: 跳点搜索(Jump Point Search,JPS)算法:一种用于路径规划的启发式搜索算法。它主要用于在网格地图(如游戏地图、机器人运动规划地图等)中快速找到从起点到终点的最短路径。该算法在改进 A*算法的基础上进行了优化,通过跳过一…

【在Linux世界中追寻伟大的One Piece】Socket编程TCP

目录 1 -> TCP socket API 2 -> V1 -Echo Server 2.1 -> 测试多个连接的情况 1 -> TCP socket API socket()&#xff1a; socket()打开一个网络通讯端口&#xff0c;如果成功的话&#xff0c;就像open()一样返回一个文件描述符。应用程序可以像读写文件一样用r…

一个vue3的待办列表组件

一个vue3的待办列表组件, 仿企业微信的待办列表 TodoList.vue <template><div><el-input v-model"todoInput" placeholder"写下你的待办事项..." class"el-input" keyup.enter"addTodo"input-style"background-c…

Chromium HTML Input 类型password 对应c++

一、密码字段&#xff1a; 密码字段通过标签 <input type"password"> 来定义: <form> Password: <input type"password" name"pwd"> </form> 二、password 对应c定义&#xff1a; third_party\blink\renderer\core\…

VR动捕数据手套如何配合头显装置进行机器臂遥操作?

早期的遥操作机器人主要通过直接控制结构实现&#xff0c;用户通过主机通讯接口直接控制机器人的运动。然而&#xff0c;随着应用场景的复杂化&#xff0c;直接控制结构的局限性逐渐显现。进入21世纪&#xff0c;随着5G、AI和VR等新兴技术的融入&#xff0c;遥操作机器人变得更…

记录一个跳跃的小游戏

记录一个跳跃的小游戏 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevic…

Lua语法基础全面剖析(中篇)

接上篇&#xff0c; 今天我们来进行Lua语法全面剖析。 由于篇幅过长&#xff0c;将分为上中下三篇进行讲解&#xff0c;本篇为中篇。 6.字符串 6.1 string 类型变量 字符串&#xff08;即string&#xff09;&#xff0c;就是一串文本数据&#xff0c;可以存储你要的文本。 …