Websocket是什么样的协议,具体有什么优点
首先,WebSocket是HTML5出的东西(协议),Websocket是一个持久化的协议, 而HTTP是一种非持久的协议
服务器推送消息到前端实现页面数据实时刷新项目链接如下:https://blog.csdn.net/pengff1234/article/details/114520623
websocket的使用步骤:
- 建立websocket连接后,
- 客户端(前端)可以发送指令给后端,
- 后端如果有数据就返回,
- 此时前端可以接收到消息,进行音频的播放
实现步骤:
1: 案例:【实现--实时接收消息提醒并语音播报】
从此连接下载必须的js:https://gitee.com/jqn-room/case-code/tree/master/websocket/static
sockjs.min.js 和 stomp.min.js
/*
audio音频:
src:是音频路径,
preload:是否预加载,
muted:静音,现在浏览器不支持自动播放音频,
autoplay:自动播放,即便音频你没有设置为静音,在页面加载的时候也不会播放音频的。
因此先设置为静音,然后需要播放音频的时候,将音频的静音取消,然后重置音频从头开始进行播放即可。
*/
<template>
<div id="wrap">
<p>
<audio src="./remind.mp3" id="audio" preload="auto" muted autoplay type="audio/mp3" controls="controls">
<span id="audioId">播放音乐</span>
</audio>
</p>
</div>
</template>
<script src="dist/js/sockjs.min.js"></script>
<script src="dist/js/stomp.min.js"></script>
<script>
export default {
data () {
return : {}
},
methods: {
websocket () {
var websocket = null;
// 1: websocket 实例化
// 判断当前浏览器是否支持websocket
if ("websocket" in window) {
websocket = new WebSocket("wss://echo.websocket.org");
//上面的这个"wss://echo.websocket.org"是从别的地方找来的,后端会提供的……,此时仅用于测试使用
// 2: websocket建立连接
var setIntervalWesocketPush = null;
websocket.onopen = (e) => {
console.log("建立连接");//建立连接后,send发送消息给后端,具体的内容可以前后端定义好,此处为"ping"
clearInterval(setIntervalWesocketPush);//下面的代码是清理定时器,并重启定时器,每隔15s发送一次消息
websocket.send("ping"); // 发送消息
setIntervalWesocketPush = setInterval(() => {
websocket.send("ping");
}, 15000);
};
//后端接收到消息后,可以发送数据给前端,前端就可以接收到了
// 3: websocket 接收消息
websocket.onmessage = (e) => {
console.log("收到消息:" + e.data);
// 获取音频:之前我都是用$("#audio")获取音频,但是执行:$("#audio").play()方法是会报错
var audio = document.querySelector("audio");//用这种标签名称获取的方式就不会报错了,,,,
audio.currentTime = 0;//从头开始播放
audio.muted = false;//取消静音
audio.play();//音频播放
};
// 4: websocket 通信错误
websocket.onerror = (e) => {
alert("websocket通信发生错误");
};
// 5: websocket 关闭连接
websocket.onclose = (e) => {
console.log("连接关闭");
clearInterval(setIntervalWesocketPush);
websocket.close(); // 关闭WebSocket连接
};
} else {
alert("您的浏览器不支持websocket")
}
}
},
mouted () {
window.addEventListener('unload', e => this.unloadHandler(e))
this.websocket()
},
destroyed() {
window.removeEventListener('unload', e => this.unloadHandler(e))
}
}
</script>
2: 案例2 【实现一个实时聊天功能】
项目链接地址:https://gitee.com/jqn-room/case-code/tree/master/websocket/websockChat-master
问题拓展:
我想实现用户登录之后一直保持websocket连接,也就是多页面共享一个websocket,当其他户给他发信息时后端立马就转发给他,如果不在线,就存储消息,等他上线在发给他,这个功能怎么实现呢???答: 可以在登录的时候,在根页面(或者在多页面外再包一层页面)里面建立websocket连接,后端收到消息可以先判断当前这个人是否有对应session存在,用户是否在线。
不在线可以先存redis或者数据库,等到下一次用户登录建立sockekt的时候再进行判断 和 发送。
前端通过socket收到消息再去进行对应的业务展示或者业务调用
WebSocket模拟库插件:SockJS
01 SockJS简介
- 在传输方式的选择方面,SockJS 会优先采用 websocket,然后再自动降级;
- 其 API 几乎与 websocket API 的使用方式相同;
- 兼容跨浏览器,支持跨域。
SockJS 是一个浏览器上运行的 JavaScript 库,如果浏览器 不支持 WebSocket 的情况下,也可以很简单地实现WebSocket的功能的,方法就是使用 SockJS。该库可以模拟对 WebSocket 的支持,实现浏览器和 Web 服务器之间低延迟、全双工、跨域的通讯通道。
它会 优先选择WebSocket 进行连接,但是当服务器或客户端不支持WebSocket时,会自动在 XHR流、XDR流、iFrame事件源、iFrame HTML文件、XHR轮询、XDR轮询、iFrame XHR轮询、JSONP轮询 这几个方案中择优进行连接。
幸运的是,我们不需要知道这些方案都代表什么,只需要简单地设置就可以使用了。
实现步骤如下:
服务端-后端
在启动WebSocket的配置中,你需要做的所有事情就是加上 withSockJS()
public void registerWebSocketHandlers(WebSocketHandlerRegistry) {
// withSockJS 声明启用支持 sockJS
webSocketHandlerRegistry.addHandler(marcoHandler(), "/echo").withSockJS();
}
客户端-前端
在客户端需要引入SockJS库,然后把 new WebSocket(url); 替换成 new SockJS(url);SockJS类 和 WebSocket类是兼容的,所以可以直接替换
<template> </template> <script> import SockJS from 'sockjs-client' import Stomp from 'stompjs' export default { data () { return { ws: null, username: '', identity: '', stompClient: null, userId: '', auctionData: { landId: '' } } }, methods: { // 创建连接方法 connection (url, headers) { // 建立连接 // 动态的连接地址 url 和 订阅的数据 headerData if ('WebSocket' in window) { // 建立连接对象 const socket = new SockJS(url) // 获取STOMP子协议的客户端对象 this.stompClient = Stomp.over(socket) this.stompClient.connect(headers, this.callbackSuccess, this.callbackError) } else { alert('当前浏览器 Not support websocket') } }, callbackSuccess () { // websocket的返回成功的方法,可在里面进行具体的监听接口和路径的配置 console.log('建立连接成功') // subscribe订阅服务端提供的某个topic(主题) this.stompClient.subscribe('/topic/' + this.auctionData.auctionId + '/auctionStart/getResponse', (msg) => { // 业务操作 }) // subscribe订阅服务端提供的某个topic(主题) this.stompClient.subscribe('/topic/' + this.auctionData.auctionId + '/rotationSettlement/getResponse', (msg) => { // 业务操作 }) // subscribe订阅服务端提供的某个topic(主题) this.stompClient.subscribe('/topic/' + this.auctionData.auctionId + '/auctionOver/getResponse', (msg) => { // 业务操作 }) // 监听轮次完成 this.stompClient.subscribe('/topic/' + this.auctionData.auctionId + '/rotationOver/getResponse', (msg) => { // 业务操作 }) // 完成一个流程 开启新轮询 this.stompClient.subscribe('/user/' + this.userId + '/' + this.auctionData.auctionId + '/getResponse', (res) => { console.log(res + 'user') const result = JSON.parse(res.body) if (result.code === 200) { this.query() // 完成后新业务逻辑,或创建新的轮询等 } else { console.log(result.msg) } }) }, callbackError (err) { // websocket的返回失败的方法 console.log(err) this.disconnect(); // 断开连接 }, disconnect () { // 断开连接的方法 console.log(this.stompClient) if (this.stompClient) { this.stompClient.disconnect() this.stompClient = null } }, // 根据状态判断是否开始通信 initConnect () { var url if (location.hostname === '192.168.10.143' || location.hostname === 'localhost' || location.hostname === '127.0.0.1') { url = 'http://121.40.115.212' // 本地测试地址 } else { url = `https://${location.hostname}/proxy` // 线上地址 } this.connection( // 开始连接 `${url}/api/development/websocket/ws`, { name: this.userId, landId: this.auctionData.landId } ) } }, mounted() { this.initConnect() }, beforeDestroy() { // 在页面关闭或销毁时关闭socket this.disconnect(); // 断开连接 } } </script> <style> </style>
需要做的事情就是这么多
效果展示
1: 支持 WebSocket
当浏览器 和 服务器都支持 websocket 的时候,直接使用websocket连接
2: 不支持WebSocket
不支持WebSocket的场景有:
浏览器不支持
Web容器不支持,如tomcat7以前的版本不支持WebSocket
防火墙不允许
Nginx没有开启WebSocket支持
当遇到不支持WebSocket的情况时,SockJS会尝试使用其他的方案来连接,刚开始打开的时候因为需要尝试各种方案,所以会阻塞一会儿,之后可以看到连接有异常,那就是尝试失败的情况。
为了测试,我使用Nginx做反向代理,把www.test.com指到项目启动的端口上,然后本地配HOST来达到模拟真实场景的效果。
因为Nginx默认是不支持WebSocket的,所以这里模拟出了服务器不支持WebSocket的场景。