海南省建设银行官方网站招聘,企业站群cms,南海区建设局网站首页,十堰做网站公司文章目录 一、WebSocket简介#xff1a;二、WebSocket通信原理及机制#xff1a;三、WebSocket特点和优点#xff1a;四、WebSocket心跳机制#xff1a;五、在后端Spring Boot 和前端VUE中如何建立通信#xff1a;【1】在Spring Boot 中 pom.xml中添加 websocket依赖【2】… 文章目录 一、WebSocket简介二、WebSocket通信原理及机制三、WebSocket特点和优点四、WebSocket心跳机制五、在后端Spring Boot 和前端VUE中如何建立通信【1】在Spring Boot 中 pom.xml中添加 websocket依赖【2】创建 WebSocketConfig.java 开启websocket支持【3】创建 WebSocketServer.java 链接【4】创建一个测试调用websocket发送消息 TimerSocketMessage.java (用定时器发送推送消息)【5】在VUE中创建和后端 websocket服务的连接并建立心跳机制【6】启动项目开始测试结果 一、WebSocket简介 HTML5规范在传统的web交互基础上为我们带来了众多的新特性随着web技术被广泛用于web APP的开发这些新特性得以推广和使用而websocket作为一种新的web通信技术具有巨大意义。WebSocket是HTML5新增的协议它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道比如说服务器可以在任意时刻发送消息给浏览器。支持双向通信。 二、WebSocket通信原理及机制 websocket是基于浏览器端的web技术那么它的通信肯定少不了http,websocket本身虽然也是一种新的应用层协议但是它也不能够脱离http而单独存在。具体来讲我们在客户端构建一个websocket实例并且为它绑定一个需要连接到的服务器地址当客户端连接服务端的时候会向服务端发送一个消息报文 三、WebSocket特点和优点 支持双向通信实时性更强。更好的二进制支持。较少的控制开销。连接创建后ws客户端、服务端进行数据交换时协议控制的数据包头部较小。在不包含头部的情况下服务端到客户端的包头只有2~10字节取决于数据包长度客户端到服务端的的话需要加上额外的4字节的掩码。而HTTP协议每次通信都需要携带完整的头部。支持扩展。ws协议定义了扩展用户可以扩展协议或者实现自定义的子协议。比如支持自定义压缩算法等建立在tcp协议之上服务端实现比较容易数据格式比较轻量性能开销小通信效率高和http协议有着良好的兼容性默认端口是80和443,并且握手阶段采用HTTP协议因此握手的时候不容易屏蔽能通过各种的HTTP代理 四、WebSocket心跳机制 在使用websocket过程中可能会出现网络断开的情况比如信号不好或者网络临时性关闭这时候websocket的连接已经断开而浏览器不会执行websocket 的 onclose方法我们无法知道是否断开连接也就无法进行重连操作。如果当前发送websocket数据到后端一旦请求超时onclose便会执行这时候便可进行绑定好的重连操作。心跳机制是每隔一段时间会向服务器发送一个数据包告诉服务器自己还活着同时客户端会确认服务器端是否还活着如果还活着的话就会回传一个数据包给客户端来确定服务器端也还活着否则的话有可能是网络断开连接了。需要重连~ 五、在后端Spring Boot 和前端VUE中如何建立通信
【1】在Spring Boot 中 pom.xml中添加 websocket依赖
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-websocket/artifactId
/dependency【2】创建 WebSocketConfig.java 开启websocket支持
package com.example.demo.websocket;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** 开启WebSocket支持* author zh*/
Configuration
public class WebSocketConfig {Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}【3】创建 WebSocketServer.java 链接
package com.example.demo.websocket;import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;ServerEndpoint(/websocket/testsocket)
Component
public class WebSocketServer {private static Logger log LoggerFactory.getLogger(WebSocketServer.class);//静态变量用来记录当前在线连接数。应该把它设计成线程安全的。private static int onlineCount 0;//concurrent包的线程安全Set用来存放每个客户端对应的MyWebSocket对象。private static CopyOnWriteArraySetWebSocketServer webSocketSet new CopyOnWriteArraySetWebSocketServer();//与某个客户端的连接会话需要通过它来给客户端发送数据private Session session;/*** 连接建立成功调用的方法*/OnOpenpublic void onOpen(Session session) {this.session session;webSocketSet.add(this); //加入set中addOnlineCount(); //在线数加1log.info(有新窗口开始监听,当前在线人数为 getOnlineCount());try {sendMessage(连接成功);} catch (Exception e) {log.error(websocket IO异常);}}/*** 连接关闭调用的方法*/OnClosepublic void onClose(Session session) {try {webSocketSet.remove(this); //从set中删除subOnlineCount(); //在线数减1session.close();log.info(有一连接关闭当前在线人数为 getOnlineCount());} catch (IOException e) {e.printStackTrace();}}/*** 收到客户端消息后调用的方法** param message 客户端发送过来的消息*/OnMessagepublic void onMessage(String message, Session session) {log.info(收到的信息:message);MapString, Object maps new HashMap();maps.put(type, message);this.sendInfo(maps);}/**** param session* param error*/OnErrorpublic void onError(Session session, Throwable error) {log.error(发生错误);error.printStackTrace();}/*** 实现服务器主动推送*/public void sendMessage(Object obj) {try {synchronized (this.session) {this.session.getBasicRemote().sendText((JSON.toJSONString(obj)));}} catch (Exception e) {e.printStackTrace();}}/*** 群发自定义消息* */public static void sendInfo(Object obj) {for (WebSocketServer item : webSocketSet) {try {item.sendMessage(obj);} catch (Exception e) {continue;}}}public static synchronized int getOnlineCount() {return onlineCount;}public static synchronized void addOnlineCount() {WebSocketServer.onlineCount;}public static synchronized void subOnlineCount() {WebSocketServer.onlineCount--;}
}【4】创建一个测试调用websocket发送消息 TimerSocketMessage.java (用定时器发送推送消息)
package com.example.demo.websocket;import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;Component
EnableScheduling
public class TimerSocketMessage {/*** 推送消息到前台*/Scheduled(cron */1 * * * * * )public void SocketMessage(){MapString, Object maps new HashMap();maps.put(type, sendMessage);maps.put(data,11111);WebSocketServer.sendInfo(maps);}
}【5】在VUE中创建和后端 websocket服务的连接并建立心跳机制
templatediv classhelloh1 websocket 消息推送测试{{data}}/h1/div
/templatescriptexport default {name: HelloWorld,data () {return {data:0,timeout: 28 * 1000,//30秒一次心跳timeoutObj: null,//心跳心跳倒计时serverTimeoutObj: null,//心跳倒计时timeoutnum: null,//断开 重连倒计时websocket: null,}},created () {// 初始化websocketthis.initWebSocket()},methods:{initWebSocket () {let url ws://localhost:8086/websocket/testsocketthis.websocket new WebSocket(url)// 连接错误this.websocket.onerror this.setErrorMessage// 连接成功this.websocket.onopen this.setOnopenMessage// 收到消息的回调this.websocket.onmessage this.setOnmessageMessage// 连接关闭的回调this.websocket.onclose this.setOncloseMessage// 监听窗口关闭事件当窗口关闭时主动去关闭websocket连接防止连接还没断开就关闭窗口server端会抛异常。window.onbeforeunload this.onbeforeunload},reconnect () { // 重新连接if(this.lockReconnect) return;this.lockReconnect true;//没连接上会一直重连设置延迟避免请求过多this.timeoutnum clearTimeout(this.timeoutnum);this.timeoutnum setTimeout(() {//新连接this.initWebSocket();this.lockReconnect false;}, 5000);},reset () { // 重置心跳// 清除时间clearTimeout(this.timeoutObj);clearTimeout(this.serverTimeoutObj);// 重启心跳this.start();},start () { // 开启心跳this.timeoutObj clearTimeout(this.timeoutObj);this.serverTimeoutObj clearTimeout(this.serverTimeoutObj);this.timeoutObj setTimeout(() {// 这里发送一个心跳后端收到后返回一个心跳消息if (this.websocket this.websocket.readyState 1) { // 如果连接正常this.websocketsend(heartbeat);} else { // 否则重连this.reconnect();}this.serverTimeoutObj setTimeout(() {//超时关闭this.websocket.close();}, this.timeout);}, this.timeout)},setOnmessageMessage (event) {let obj JSON.parse(event.data);console.log(obj,obj)switch(obj.type) {case heartbeat://收到服务器信息心跳重置this.reset();break;case sendMessage:this.data obj.dataconsole.log(接收到的服务器消息,obj.data)}},setErrorMessage () {//重连this.reconnect();console.log(WebSocket连接发生错误 状态码 this.websocket.readyState)},setOnopenMessage () {//开启心跳this.start();console.log(WebSocket连接成功 状态码 this.websocket.readyState)},setOncloseMessage () {//重连this.reconnect();console.log( WebSocket连接关闭 状态码 this.websocket.readyState)},onbeforeunload () {this.closeWebSocket();},//websocket发送消息websocketsend(messsage) {this.websocket.send(messsage)},closeWebSocket() { // 关闭websocketthis.websocket.close()},}
}
/script!-- Add scoped attribute to limit CSS to this component only --
style scoped
h1, h2 {font-weight: normal;
}
ul {list-style-type: none;padding: 0;
}
li {display: inline-block;margin: 0 10px;
}
a {color: #42b983;
}
/style【6】启动项目开始测试结果