今日简单总结 websocket 使用过程中遇到的问题,主要从以下三个方面来分享:
1、前端部分 websocket 代码
2、使用 koa.js 实现后端 websocket 服务搭建
3、和后端 java Netty 库对接时遇到连接失败问题
一、前端部分 websocket 代码
<template><div id="app"><div v-for="item in messages" :key="item.id">{{ item.value }}</div><el-form :inline="true"><el-form-item label="消息:"><el-input v-model="newMessage" placeholder="请输入内容"></el-input></el-form-item><el-form-item><el-button type="primary" @click="sendMessage">发送</el-button></el-form-item></el-form><router-view /></div>
</template><script>
export default {name: 'App',data() {return {messages: [],newMessage: '',socket: null,};},created() {this.initializeWebSocketConnection();},beforeDestroy() {if (this.socket) {this.socket.close();}},methods: {initializeWebSocketConnection() {// 建立连接this.socket = new WebSocket('ws://localhost:8083');// 客户端向服务端发送消息this.socket.onopen = () => {this.socket.send(JSON.stringify({value: this.newMessage,}));};// 客户端接收服务端的消息this.socket.onmessage = (event) => {const res = JSON.parse(event.data);this.messages.push(res.data);};// 错误处理this.socket.onerror = (error) => {console.error('WebSocket Error:', error);};// 关闭this.socket.onclose = () => {console.log('WebSocket connection closed');};},sendMessage() {// 手动向服务端发送消息if (this.socket.readyState === WebSocket.OPEN) {this.socket.send(JSON.stringify({value: this.newMessage,}));this.newMessage = '';} else {console.error('Cannot send message, the socket is not open.');}},},
};
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;
}
</style>
二、使用 koa.js 实现后端 websocket 服务搭建
// app.js
const Koa = require('koa');
const WebSocket = require('ws');
const { v4: uuidv4 } = require('uuid');const app = new Koa();
const wss = new WebSocket.Server({port: 8083,
});// 存储所有连接的客户端
const clients = new Set();wss.on('connection', (ws) => {// 新客户端连接时添加到clients集合中clients.add(ws);console.log('WebSocket connection opened');ws.on('message', (message) => {console.log('Received message from client:', message);try {console.log('clients::', clients);// 将接收到的字符串转换为JSON对象const data = JSON.parse(message);// 在此处处理接收到的JSON数据console.log('Received data:', data);const response = {status: '200',message: 'success',data: {id: uuidv4(),value: data.value,},};// 将响应的JSON对象转换为字符串并通过WebSocket发送ws.send(JSON.stringify(response));} catch (error) {console.error('Error parsing JSON:', error);// 如果解析失败,发送错误消息回客户端ws.send(JSON.stringify({ error: 'Invalid JSON format' }));}});ws.on('close', () => {// 客户端关闭连接时从clients集合中移除clients.delete(ws);console.log('WebSocket connection closed');});ws.on('error', (error) => {console.error('WebSocket error:', error);});
});// 假设这个函数会在数据状态改变时被调用
function onDataStateChange(newData) {// 遍历所有客户端连接并发送消息for (const client of clients) {if (client.readyState === WebSocket.OPEN) {client.send(JSON.stringify({status: '200',message: 'success',data: {id: uuidv4(),value: '数据发生改变啦...',},})); // 发送新数据到客户端}}
}// 示例:模拟数据状态改变并推送消息
setTimeout(() => {const newData = { status: 'updated', value: 'New Value' };onDataStateChange(newData); // 模拟数据状态改变,并向所有客户端推送消息
}, 10000); // 5秒后模拟数据改变app.use(async (ctx) => {ctx.body = 'Hello, Koa!';
});app.listen(3000, () => {console.log('Server is running on port 3000');
});
三、和后端 java Netty 库对接时遇到连接失败问题
前端在 1、2 步骤的验证时,websocket 成功建立连接,消息可以正常发送,但是在和后端小伙伴联调时,请求头一直报 Provisional headers are shown 错误,如下图:
原因,后端 java 在使用 Netty 库创建 webSocket 通信时,未添加协议处理器,当后端添加完协议处理器后,前端在进行通信的时候,需要在加上这个前缀,如下图:
前端的修改,如下图:
解决之后的请求头:
可以在 Messages 中看到消息推送,当客户端和服务端建立连接之后,客户端可以向服务端发送消息,服务端也可以向客户端推送消息,实现即时通信功能。如下图: