今日简单总结 websocket 使用过程中遇到的问题,主要从以下三个方面来分享:
1、前端部分 websocket 代码
2、使用 koa.js 实现后端 websocket 服务搭建
3、和后端 java Netty 库对接时遇到连接失败问题
一、前端部分 websocket 代码
- <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>
-
- <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 中看到消息推送,当客户端和服务端建立连接之后,客户端可以向服务端发送消息,服务端也可以向客户端推送消息,实现即时通信功能。如下图:
