前言
在一次react + koa项目中需要实现私信的功能,当时没有了解过websocket所以是使用轮询的方式来实现的,但是用轮询的方式做出来的体验有些差,后面又去了解了一下websocket的实现方式。
WebSocket简介
WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
具体实现
服务端
import { WebSocketServer, WebSocket } from 'ws'
// 连接列表
const clients: { ws: WebSocket; uid: string }[] = []
export function createWebSocket() {
const wss = new WebSocketServer({
port: 3001
})
wss.on('connection', (ws) => {
// 接收信息
ws.on('message', (message) => {
console.log('连接成功')
const msg = JSON.parse(message.toString('utf-8'))
if (msg.uid) {
// 首次连接
if (!clients.includes(msg.uid)) {
clients.push({ ws, uid: msg.uid })
}
if (msg.reciveId) {
const index = clients.findIndex((item) => item.uid === msg.reciveId)
if (index === -1) {
ws.send(JSON.stringify({ content: '用户还未上线' }))
} else {
if (msg.content) {
clients[index].ws.send(
JSON.stringify({ content: msg.content, sendId: msg.uid })
)
}
}
}
}
})
// 关闭连接
ws.on('close', (ws) => {
console.log('close')
})
})
}
createWebSocket()
前端,在localStorage里面提前存一个uid模拟用户id
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
接收方: <input type="text" id="reciveId" /> <br />
发送信息: <input type="text" id="content" /><br />
<button onClick="send()">发送</button><br />
服务器返回的信息:
<ul id="msg-list"></ul>
</body>
<script>
const uid = localStorage.getItem('uid')
let ws
ws = new WebSocket('ws://localhost:3001')
// 连接
ws.onopen = (event) => {
ws.send(JSON.stringify({ uid }))
}
// 接收信息
ws.onmessage = (event) => {
const { content, sendId } = JSON.parse(event.data)
const list = document.getElementById('msg-list')
const li = document.createElement('li')
if (sendId) {
li.innerHTML = `发送者:${sendId} 内容:${content}`
} else {
li.innerHTML = `${content}`
}
list.appendChild(li)
}
const send = () => {
const reciveId = document.getElementById('reciveId')
const content = document.getElementById('content')
ws.send(
JSON.stringify({
uid,
reciveId: reciveId.value,
content: content.value
})
)
}
</script>
</html>
效果