这里写自定义目录标题
前言
由于项目需要定时将消息从Web端推送至客户端
通常使用的方式有:AJAX轮询、XHR长轮询、iframe、Comet、websocket等
部分详情可见:https://blog.csdn.net/qq_43225978/article/details/105396640
考虑实现的难度及复杂度,最终选用WebSocket方式。
WebSocket 简介
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。
当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。
以下 API 用于创建 WebSocket 对象。
WebSocket 简介及API
https://www.runoob.com/html/html5-websocket.html
http://www.ruanyifeng.com/blog/2017/05/websocket.html
https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket
WebSocket 客户端(javascript前端)实现
javascript 实现
// 心跳重试连接次数
var websocket_reconnected_count = 0;
var websocket = null;
// 初始化WebSocket连接
function initWebSocket() {
websocket = null;
// 判断当前环境是否支持websocket
if(window.WebSocket){
if(!websocket){
// 获取协议类型
var protocol = window.location.protocol;
// console.info(protocol)
// 通过访问协议类型,判断使用的websocket协议类型
var ws_url = protocol=='http:'?'ws://':'wss://'
// 获取域名
var host = window.location.host;
// 获取端口号
var port = window.location.port;
// 获取项目访问路由
var pathName = window.location.pathname;
// 截取项目名
var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
// 拼接websocket访问地址
ws_url += host + projectName + "/webSocket/user_1";
// console.info(ws_url);
// 创建websocket对象
websocket = new WebSocket(ws_url);
}
}else{
var content = '【当前浏览器不支持WEBSOCKET,无法获取预警提醒消息,为获得良好的使用体验,推荐您下载使用<a style="color: orange;text-decoration: underline;" target="_blank" href="https://xxx.xxx.com/updown/41_chrome_installer.exe">Chrome浏览器</a>】';
alter(content);
}
//连接成功建立的回调方法
websocket.onopen = function () {
console.log('WebSocket连接成功');
// 成功建立连接后,重置心跳检测
heartCheck.reset().start();
}
//连接发生错误的回调方法
websocket.onerror = function () {
console.log('WebSocket连接发生错误');
};
//接收到消息的回调方法
websocket.onmessage = function (event) {
// console.log("=====WebSocket接收到消息=====");
// console.log(event);
// console.log(event.data);
// 当服务端的会话不存在时,返回标志
if(event.data=="\"sessionIsNulltrue\""){
// 断开ws
websocket.close();
// 因为是会话过期,所以心跳重试链接机制的次数websocket_reconnected_count归零
websocket_reconnected_count=0;
// 重置清空心跳
heartCheck.reset();
// 使用layui弹窗提醒
parent.layer.open({
content: "会话过期!请重新登录!"
,btn: '确定',
closeBtn : false,
yes: function(index, layero){
//按钮【按钮一】的回调
// console.info("=======")
parent.layer.closeAll();
// 跳转至主页
window.top.location.href = Common.ctxPath + "/"
}
});
}
// 如果获取到消息,说明连接是正常的,重置心跳检测
heartCheck.reset().start();
}
//连接关闭的回调方法
websocket.onclose = function () {
console.log('WebSocket连接关闭');
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
// 关闭WebSocket连接
websocket.close();
}
}
// 心跳检测, 每隔一段时间检测连接状态,如果处于连接中,就向server端主动发送消息,来重置server端与客户端的最大连接时间,如果已经断开了,发起重连。
var heartCheck = {
// 30s 发一次心跳,比server端设置的连接时间稍微小,在接近断开的情况下以通信的方式去重置连接时间。
timeout: 30000,
serverTimeoutObj: null,
reset: function(){
var self = this;
clearTimeout(self.timeout);
clearInterval(self.serverTimeoutObj);
return self;
},
start: function(){
var self = this;
this.serverTimeoutObj = setInterval(function(){
if(websocket.readyState == 1){
console.log("连接状态,心跳保持连接");
websocket.send("ping");
heartCheck.reset().start(); // 如果获取到消息,说明连接是正常的,重置心跳检测
}else{
if(websocket_reconnected_count>0){
--websocket_reconnected_count;
console.log