WebSocket

概述

WebSocket是一种在单个TCP连接上进行全双工通信的网络协议,它是HTML5中的一种新特性

WebSocket能实现Web应用程序和服务器之间的实时通信,比如在线聊天、游戏、数据可视化等

相较HTTP协议的请求-响应模式,使用WebSocket可以建立持久连接,允许服务器主动向客户端推送数据,避免不必要的轮询请求,提高了实时性和效率

同时,WebSocket的连接过程也比较简单,可以通过JavaScript WebSocket API进行创建和管理,还可以和现有的Web技术如HTML、CSS和JavaScript无缝集成

WebSocket协议基于握手协议 (Handshake Protocol),它在建立连接时使用HTTP/HTTPS发送一个初始握手请求,然后服务器响应该请求,建立连接后就可以在连接上进行数据传输了

总之,WebSocket提供了一种使Web应用程序能够实现的、实时通信的快速、可靠且灵活的方式,同时也提高了网络性能和用户体验

适用场景

  • 实时性要求较高的应用,比如在线聊天、游戏、数据可视化等
  • 需要频繁交换数据的应用,比如在线编辑器、文件管理器等
  • 需要推送服务的应用,比如实时数据监控、通知系统等
  • 跨平台的应用,比如桌面应用程序、移动应用程序等

使用

安装依赖:

1
2
pnpm install ws
pnpm install @types/ws -D

后端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import ws from 'ws'

// 创建socket服务
const wss = new ws.Server({port:8080}, ()=> {
console.log('服务启动成功')
})

// 定义向客户端发送的消息的类型
const state = {
HEART: 1,
MESSAGE: 2
}

// 监听客户端的连接是否成功
wss.on('connection', (socket)=> {
console.log(socket)
// 接收客户端的消息
socket.on('message', (msg)=> {
// clients是一个set,它记录了连入socket的用户,通过遍历实现在用户中广播
wss.clients.forEach((client)=> {
// 向客户端返回消息
socket.send(JSON.stringify({
type: state.MESSAGE,
message: msg.toString()
}))
})
})

// 心跳检测
// WebSocket可能会因网络波动、弱信号等而断连
// 为了避免断连,可以使用心跳机制检测WebSocket连接是否正常
// 当发现连接断开时,可以尝试重新建立连接,并进行相应的处理(保活)
let heartInterval: any = null
const heartCheck = ()=> {
// socket状态为open时才给前端发送心跳
if(socket.readyState === ws.OPEN) {
socket.send(JSON.stringify({
type: state.HEART,
message: '心跳检测'
}))
} else {
// 否则就是关闭状态
clearInterval(heartInterval)
}
}

// 服务端每隔五秒向前端发送一次心跳
heartInterval = setInterval(heartCheck, 5000)
})

前端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
const ul = document.getElementById("list")
const input = document.getElementById("input")
const send = document.getElementById("send")
const stop = document.getElementById("stop")

// WebSocket实例;协议是ws://或wss://,类似http://和https://
const ws = new WebSocket('ws://localhost:8080')

// 监听客户端的连接是否成功
ws.addEventListener('open', (event)=> {
console.log('连接成功')
})

send.addEventListener('click', ()=> {
// 给服务端发送消息
if(input.value) {
ws.send(input.value)
input.value = ""
}
})

// 接收服务端的消息
ws.addEventListener('message', (msg)=> {
const data = JSON.parse(msg.data)
if(data.type==2) {
// 把消息加进列表,不添加心跳
const li = document.createElement("li")
li.innerText = data.message
ul.appendChild(li)
}
})

stop.addEventListener('click', ()=> {
// 调用close方法主动断开连接
ws.close()
})