今日简单总结 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 中看到消息推送,当客户端和服务端建立连接之后,客户端可以向服务端发送消息,服务端也可以向客户端推送消息,实现即时通信功能。如下图: