websocket是什么
HTML5开始提供的一种浏览器与服务器之间进行全双工通讯的网络技术,属于应用层协议。它基于TCP传输协议,并复用HTTP的握手通道。浏览器和服务器只需完成一次握手,两者之间就可以直接建立持久性的连接,并且进行双向数据传输,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯(例如:微信聊天就属于双向数据传输)。
在 webSocket 之前很多网站使用推送技术,所用的都是ajax轮询。轮询是在规定的时间间隔中通过http向服务器发送请求,然后接收服务器的响应。这种方式需要浏览器不断的向服务器发送请求,就显得繁琐,并且http请求可能包含较长头数据,显然这样会浪费很多的带宽等资源。
websocket 相对于http的优点
1、支持双向通信,实时性更强。
2、更好的二进制支持(websocket是以二进制数据推送过来的)。
3、较少的控制开销。连接创建后,ws客户端、服务端进行数据交换时,协议控制的数据包头部较小。在不包含头部的情况下,服务端到客户端的包头只有2~10字节(取决于数据包长度),客户端到服务端的的话,需要加上额外的4字节的掩码。而HTTP协议每次通信都需要携带完整的头部。
支持扩展。ws协议定义了扩展,用户可以扩展协议,或者实现自定义的子协议。(比如支持自定义压缩算法等)
websocket建立连接
//建立连接以后,客户端和服务器端就可以通过 TCP 连接直接交换数据,可用 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据
/*
url:建立 websocket url
protocol: 子协议
*/
var Socket = new WebSocket(url, [protocol] );
Websocket属性
// Socket.readyState(表示连接状态)
0 - 表示连接尚未建立。
1 - 表示连接已建立,可以进行通信。
2 - 表示连接正在进行关闭。
3 - 表示连接已经关闭或者连接不能打开。
websocket事件
事件 事件处理程序 描述
open Socket.onopen 连接建立时触发
message Socket.onmessage 客户端接收服务端数据时触发
error Socket.onerror 通信发生错误时触发
close Socket.onclose 连接关闭时触发
websocket方法
//使用连接向服务器发送数据
Socket.send()
// 关闭websocket连接
Socket.close()
封装websocket函数
class WebsocketJs{
constructor({socket,
socket_url, //ws 路径
socket_open=false, //开启标志
hearbeat_timer, //心跳定时器
hearbeat_interval= 5000, // 发送心跳频率
is_reonnect = true, //是否自动重连
reonnect_count = 3, //重连次数
reonnect_current = 1, //已经重连次数
reonnect_timer, //重连定时器
reonnect_interval = 5000,//重连频率
}){
this.socket = null;
this.socket_url = socket_url;
this.initSocket()
this.onmessage = null;
this.socket_open = socket_open;
this.hearbeat_timer = hearbeat_timer; //null
this.hearbeat_interval = hearbeat_interval;
this.is_reonnect = is_reonnect;
this.reonnect_timer = reonnect_timer;//null
this.reonnect_interval = reonnect_interval;
this.reonnect_current = reonnect_current;
this.reonnect_count = reonnect_count;
}
// 初始化
initSocket(){
if( !("WebSocket" in window) ){
console.log('浏览器不支持WebSocket')
return null
}
this.socket = new WebSocket(this.socket_url)
// 接收到服务器返回的数据 可以通过外部传入进行回调
this.socket.onmessage = function(e){
console.log(e)
this.receive(e)
}
// 连接上服务器
this.socket.onopen = function(e){
console.log(e) //可以做一些重连接操作
console.log('连接上服务器')
this.socket_open = true; //开启websocket
this.is_reonnect = true; //开启重连
this.hearBeat(); //开启心跳
}
//关闭连接
this.socket.onclose = function (e) {
// clearInterval(this.hearbeat_interval)
this.socket_open = false;
//是否需要重连
if (this.is_reonnect){
this.reonnect_timer = setInterval(()=>{
// 当前重连数 > 总连接数 就放弃请求
if (this.reonnect_current > this.reonnect_count){
clearTimeout(this.reonnect_timer)
return
}
// 记录重连次数
this.reonnect_current++
this.reconnect();
},this.reonnect_interval)
}
}
//连接报错
this.socket.onerror = function (e) {
console.log(e);
}
}
// 心跳(是否还活着)
hearBeat(){
// 判断之前是否有过开启过心跳
if (this.hearbeat_timer){
clearInterval(this.hearbeat_timer)
}
this.hearbeat_timer = setInterval(()=>{
this.socket.send(data) //需要向服务器发送的数据
},this.hearbeat_interval)
}
// 接收消息
receive(message){
// 获取到数据 -- 看自己业务进行修改
var params = JSON.parse(message.data)
}
// 发送消息
send(data,callback=null){
//callback()
// this.socket.OPEN 是打开时返回的状态
if (this.socket.readyState === this.socket.OPEN){
this.socket.send(JSON.stringify(data))
}else if(this.socket.readyState === this.socket.CONNECTING){// 正在开启状态,则等待1s后重新调用
setTimeout(function () {
this.send(data)//,callback
}, 1000)
}else { // 未开启,则等待1s后重新调用
this.initSocket()
setTimeout(function () {
this.send(data) //, callback
}, 1000)
}
// if (callback) {
// callback()
// }
}
// 重新连接
reconnect(){
// 重新发起连接(如果有开启则关闭)
if (this.socket && this.socket_open) {
this.close()
}
this.initSocket();
}
// 主动关闭请求
close(){
console.log('主动关闭')
clearInterval(this.hearbeat_timer)
this.is_reonnect = false
// this.socket.close()
}
}