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的场景。
参考资料:https://segmentfault.com/a/1190000019409827 ? ? ? ? ? ? ? ? ? ? ??
|