要实现客户端与服务器端的通信,最常接触的是http(https)协议,http通信只能是客户端发起请求,服务器响应。服务器不能主动向客户端传递消息。
HTTP 协议无法做到服务器主动向客户端推送信息,2008年诞生的WebSocket 协议可以实现客户端与服务器端的双向对话,即:服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息。
- WebSocket 协议的底层协议也是TCP协议
- WebSocket 协议的标识符为ws,加密后为wss
- WebSocket 协议没有同源限制,即WebSocket 协议可以跨域通信
- WebSocket 协议是有状态的,是前后端交互的长连接,即建立连接后可以保持连接状态,通信时可以省略部分状态信息
- WebSocket 协议可以发送文本,也可以发送二进制数据
客户端实现
客户端可以通过WebSocket 构造函数创建WebSocket 对象
创建和管理 WebSocket 连接,并通过该连接发送和接收数据的 API。
属性 | 说明 |
---|---|
readyState | 当前 WebSocket 的链接状态 , 0:正在链接中 1:已经链接并且可以通讯 2:连接正在关闭 3;连接已关闭或者没有链接成功 |
onopen | 连接成功后的回调 |
onerror | 连接失败后的回调 |
onmessage | 从服务器接受到信息时的回调 |
onclose | 连接关闭后的回调 |
const webSocket = new WebSocket('ws://localhost:5001')
webSocket.onopen = function () {
console.log('连接成功...')
webSocket.send('Hello!')
}
webSocket.onerror = function () {
console.log('连接失败...')
}
webSocket.onmessage = function (event) {
console.log('接收到消息...' + event.data)
}
webSocket.onclose = function () {
console.log('连接已关闭...')
}
更详情的WebSocket对象参考:https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket
WebSocket重连
由于网络的不确定性和websocket自身的问题,页面长时间打开的情况下有时会发生websocket连接的断开,为了避免这类情况引起的程序问题,可以让WebSocket对象每间隔一段时间和服务器通信一次,一旦发生异常,则重新建立连接,称为心跳检测机制,形象的说就是客户端和服务端通过发送心跳向对方证明自己还活着。
var lockReconnect = false // 是否允许重新连接
var timeout = 1000 * 20 // 心跳间隔
var reTimeout = 1000 * 10 // 重连间隔
var timeoutTimer = null // 心跳定时器
var reTimeoutTimer = null // 重连定时器
var webSocket = null
function heartCheckStart () {
timeoutTimer = setTimeout(function () {
webSocket.send('HeartBeat')
}, timeout)
}
function heartCheckReset () {
clearTimeout(timeoutTimer)
heartCheckStart()
}
function createWebSocket () {
webSocket = new WebSocket('ws://localhost:5001')
webSocket.onopen = function () {
console.log('连接成功...')
heartCheckStart()
}
webSocket.onerror = function () {
console.log('连接失败...')
reConnect()
}
webSocket.onmessage = function (event) {
console.log(event.data)
heartCheckReset()
}
webSocket.onclose = function (event) {
console.log('连接已关闭...')
console.log('websocket 断开: ' + event.code + ' ' + event.reason + ' ' + event.wasClean)
reConnect()
}
}
// 重连
function reConnect () {
if (lockReconnect) {
return
}
lockReconnect = true
// 没连接上会一直重连,设置延迟避免请求过多
reTimeoutTimer && clearTimeout(reTimeoutTimer)
reTimeoutTimer = setTimeout(function () {
createWebSocket()
lockReconnect = false
}, reTimeout)
}
createWebSocket()
服务器端实现
真实的项目中服务器端是由专人负责的,为了模拟真实的通信过程,这里简单用node搭建一个服务来实现WebSocket通信。
node搭建WebSocket服务器
要确保安装node,安装node运行环境,请下载node 安装包进行安装
一、新建文件夹demo,然后用npm init命令新建一个项目ws-demo
mkdir demo
cd demo
npm init
二、安装依赖ws
npm install ws
三、修改入口文件index.js
const WebSocket = require('ws')
const ws = new WebSocket.Server({ port: 5001 })
ws.on('connection', ws => {
console.log('server connection')
ws.on('message', msg => {
console.log('服务端接收的消息:', msg)
ws.send('HeartBeat')
})
ws.send('连接已建立')
})
四、运行index.js
node index.js