效果图
webSocket的主要功能是实现即时的双向通讯,和http通信的主要不同是:服务器在websocket中能主动地向前端发送消息,而在http中只能被动地接收请求和响应请求。
如下图所示,一共有四个客户端,一个人发送信息,所有人都会即时地接收到信息。
前端WebSocket的使用
其实前端的websocket用起来很简单,看官方文档可以发现,websocket对象的属性、方法、事件都很少,所以上手非常容易。我简要说明一下,要使用WebSocket,要做的其实就三步:
- 调用WebSocket构造函数,生成websocket对象
- 为WebSocket添加事件监听
- 调用对象的send方法,发送消息
前端的代码如下:
<!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>
<div class="container">
<div class="chat-box">
<h3>聊天内容</h3>
</div>
<textarea class="message"></textarea>
<button class="send">发送</button>
</div>
<script>
const chatBox = document.querySelector('.chat-box')
const textarea = document.querySelector('.message')
const sendButton = document.querySelector('.send')
// 生成WebSocket对象
const ws = new WebSocket('ws://localhost:9002/ws')
// 为WebSocket添加事件监听
ws.addEventListener('message', function (event) {
const li = document.createElement('li')
li.innerText = event.data
chatBox.append(li)
});
ws.addEventListener('open', () => {
console.log('websocket连接建立完毕')
})
sendButton.addEventListener('click', () => {
// 发送消息
ws.send(textarea.value)
})
</script>
<style>
.container{
width: 300px;
height: 300px;
display: flex;
flex-wrap: wrap;
align-content: space-between;
border: 2px rgb(10, 193, 89) dashed;
padding: 5px;
}
.chat-box{
padding: 0 10px;
overflow: auto;
height: 60%;
width: 100%;
border: rgb(205, 37, 37) solid 2px;
}
.chat-box > h3{
margin: 0;
text-align: center;
overflow: auto;
}
.message{
width: 100%;
height: 15%;
}
.send{
height: 15%;
width: 100%;
font-size: larger;
}
</style>
</body>
</html>
后端WebSocket服务器
后端实现一个WebSocket服务器,要比上面前端的步骤难得多得多,因为多人即时聊天这种需求,必然会涉及到多线程和线程间的通信,而且还要考虑websocket对象的失效、出错、回收等问题。我本来是想学习一下然后用golang来写这个websocket服务器的,但翻文档翻了俩小时,愣是一点没学明白,汗(lll¬ω¬)。唉,后端还是学的太少,功力不够,很多io操作、线程操作看都看不懂。
这里,我就用nodejs来实现一个简易的WebSocket服务器,具体使用的是ws库,代码如下:
// 导入WebSocket模块:
const WebSocket = require('ws');
// 引用Server类:
const WebSocketServer = WebSocket.Server;
// 实例化:
const wss = new WebSocketServer({
port: 9002,
path: '/ws'
});
let wsList = []
// 监听创建连接事件,回调函数的参数是创建的连接
wss.on('connection', function connection(ws) {
ws.on('error', console.error)
// 监听该连接的接收信息事件
ws.on('message', function message(data) {
console.log('接收到信息: %s', data)
for(let w of wsList){
if(w.readyState == w.OPEN){
w.send(data.toString())
}
}
})
wsList.push(ws)
})