websocket是一种网络通讯协议。 websocket 是HTML5开始提供的一种在单个TCP链接上进行全双工通讯的协议。
初次接触websocket,都会带着疑惑去学习,既然已经有了HTTP协议,为什么还需要另一个协议?它能带来什么好处呢?很简单,因为HTTP协议的通讯只能由客户端发起。
举列来说,我想了解今天的天气,只能是客户端向服务端发出请求,服务器返回查询结果,HTTP协议做不到服务器主动向客户端推送信息。
传统的HTTP协议是无状态的,每次请求request都要由客户端浏览器主动发起,服务端进行处理后返回response结果,而服务端很难主动向客户端发送数据了这种客户端是主动方,服务端是被动方的传统web模式,对于信息变化不频繁的web应用来说造成的麻烦较小,而对于涉及实时信息的web应用却带来了很大的不方便,如带有即时通信,实时数据,订阅推送等功能的应用。
相对于传统HTTP每次请求-应答都需要客户端与服务端简历连接的模式,websocket是类似socket的TCP长连接通讯模式,一旦websocket连接建立后,后继数据都已帧序列的形式传输,在客户端断开websocket连接活Server端终端连接前,不需要客户端和服务端重新发起连接请求,在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息实在同一个持久连接上发起,实时性优势明显。
websocket需要像TCP一样,先建立连接,需要客户端和服务端进行握手连接,连接成功后才能湘湖通信。
websocket对象作为一个构造函数,用于新建websocket实例
var ws = new webSocket("ws://127.0.0.1:8090")
执行上面语句之后,客户端就会与服务器进行连接。
readyState属性返回实例对象的当前状态,共有四种。
CONNECTING:值为0,表示正在连接。
OPEN:值为1,标识连接成功,可以通信了。
CLOSING:值为2,标识连接正在关闭。
CLOSED:值为3,标识连接已经关闭,或者打开链接失败。
连接发生错误的回调方法
ws.onerror = function(){
alert("webSocket连接发生错误“)
}
实例对象的onclose 属性,用于指定关闭连接后的回调函数
ws.onclose = function(){
alert("websocket连接关闭")
}
实例对象的send()方法用于向服务器发送数据
ws.send("your message")
总结完webSocket如何握手及其所有的方法,下面进入实战
websocket 封装的websocket.js代码
/* WebSocket封装
* @param url: WebSocket接口地址与携带参数必填
* @param onOpenFunc: WebSocket的onopen回调函数,如果不需要可传null
* @param onMessageFunc: WebSocket的onmessage回调函数,如果不需要可传null
* @param onCloseFunc: WebSocket的onclose回调函数,如果不需要可传null
* @param onErrorFunc: WebSocket的onerror回调函数,如果不需要可传null
* @param heartMessage: 发送后台的心跳包参数,必填 (给服务端的心跳包就是定期给服务端发送消息)
* @param timer: 给后台传送心跳包的间隔时间,不传时使用默认值3000毫秒
* @param isReconnect: 是否断掉立即重连,不传true时不重连
*/
function useWebSocket(
url,
onOpenFunc,
onMessageFunc,
onCloseFunc,
onErrorFunc,
heartMessage,
timer,
isReconnect
) {
let isConnected = false; // 设定已链接webSocket标记
// websocket对象
let ws = null;
// 创建并链接webSocket
let connect = () => {
// 如果未链接webSocket,则创建一个新的webSocket
if (!isConnected) {
ws = new WebSocket(url);
isConnected = true;
}
};
// 向后台发送心跳消息
let heartCheck = () => {
// for (let i = 0; i < heartMessage.length; i++) {
// ws.send(JSON.stringify(heartMessage[i]))
// }
};
// 初始化事件回调函数
let initEventHandle = () => {
ws.addEventListener('open', (e) => {
console.log('onopen', e);
// 给后台发心跳请求,在onmessage中取得消息则说明链接正常
//heartCheck()
// 如果传入了函数,执行onOpenFunc
if (!onOpenFunc) {
return false;
} else {
onOpenFunc(e, ws);
}
});
ws.addEventListener('message', (e) => {
// 接收到任何后台消息都说明当前连接是正常的
if (!e) {
console.log('get nothing from service');
return false;
} else {
// 如果获取到后台消息,则timer毫秒后再次发起心跳请求给后台,检测是否断连
setTimeout(
() => {
if (isConnected) {
heartCheck();
}
},
!timer ? 3000 : timer
);
}
// 如果传入了函数,执行onMessageFunc
if (!onMessageFunc) {
return false;
} else {
onMessageFunc(e);
}
});
ws.addEventListener('close', (e) => {
console.log('onclose', e);
// 如果传入了函数,执行onCloseFunc
if (!onCloseFunc) {
return false;
} else {
onCloseFunc(e);
}
// if (isReconnect) { // 如果断开立即重连标志为true
// // 重新链接webSocket
// connect()
// }
});
ws.addEventListener('error', (e) => {
console.log('onerror', e);
// 如果传入了函数,执行onErrorFunc
if (!onErrorFunc) {
return false;
} else {
onErrorFunc(e);
}
if (isReconnect) {
// 如果断开立即重连标志为true
// 重新链接webSocket
connect();
}
});
};
// 初始化webSocket
// (() => {
// 1.创建并链接webSocket
connect();
// 2.初始化事件回调函数
initEventHandle();
// 3.返回是否已连接
return ws;
// })()
}
export default {
useWebSocket,
};
调用方法并建立连接使用:(当连接失败后,进行websocket重连)
initWebSocket() {
if(!this.ws) {
// url
let url = 'ws://XXX.XXX.XXX.XXX:4002/websocket/11111'
this.ws = websocket.useWebSocket(
url, // url
this.wsOnOpen, // 链接回调
this.wsOnMessage, // 连接成功后处理接口返回信息
this.wsOnClose, // 关闭回调
this.wsOnError, // 消息通知错误回调
[], // 发送后台的心跳包参数
null, // 给后台传送心跳包的间隔时间
true, // 是否断掉立即重连
);
}
},
wsOnOpen() {
console.log('开始连接')
},
wsOnError(e) {
console.log(e,'消息通知错误回调,重新连接')
this.ws.close();
this.ws = null;
this.initWebSocket();
},
wsOnMessage(e) {
if(e.data != '连接成功') {
console.log(JSON.parse(e.data),'接口返回信息')
}
},
wsOnClose() {
console.log('关闭')
// 意外关闭之后重新连接
if(!this.disConnectTimer) {
this.disConnectTimer = setTimeout(() => {
this.initWebSocket()
this.disConnectTimer = null
}, 10000)
}
},