完善websocket消息确认机制

This commit is contained in:
2026-09-29 11:14:09 +08:00
parent 5e57920039
commit 9dc511f08b
2 changed files with 91 additions and 42 deletions
+90 -41
View File
@@ -43,6 +43,7 @@ function initWebSocket(server) {
console.log("WebSocket用户:", user);
const username = user.username;
ws.username = username;
// 保存连接
addConnection(username, ws);
@@ -54,20 +55,21 @@ function initWebSocket(server) {
// 接收客户端消息
ws.on("message", (message) => {
try {
const data = JSON.parse(message.toString());
console.log("收到WebSocket消息:", data);
try {
const data = JSON.parse(message.toString());
console.log("收到WebSocket消息:", data);
handleMessage(username, data);
} catch (error) {
console.error("WebSocket消息处理失败:", error);
}
});
// websocket收到消息,必须通过解析data内容才知道谁是发送者谁是接收者
handleMessage(data, ws);
} catch (error) {
console.error("WebSocket消息处理失败:", error);
}
});
// 连接关闭
ws.on("close", () => {
removeConnection(username);
// 通知所有在线用户当前在线用户列表
broadcast({
type: "userOnline",
@@ -87,13 +89,13 @@ function initWebSocket(server) {
}
// 处理WebSocket消息
function handleMessage(username, data) {
function handleMessage(data, ws) {
switch (data.type) {
case "sendMessage":
handleSendMessage(username, data);
handleSendMessage(data, ws);
break;
case "ack":
handleAck(data);
handleAck(data, ws);
break;
default:
@@ -102,21 +104,36 @@ function handleMessage(username, data) {
}
// 处理发送消息
function handleSendMessage(senderName, data) {
function handleSendMessage(data, ws) {
const senderName = ws.username;
const messageId = data.messageId;
const receiverName = data.receiverName;
const content = data.content;
if (!messageId) {
console.log("消息缺少 messageId");
return;
}
if (!receiverName) {
console.log("消息缺少接收者");
return;
}
if (!content) {
console.log("消息内容为空");
return;
}
console.log(
`${senderName} → ${receiverName}:${content}`
);
const sql = `
INSERT INTO messages
(message_id, sender_name, receiver_name, content)
VALUES (?, ?, ?, ?)
`;
INSERT INTO messages
(message_id, sender_name, receiver_name, content)
VALUES (?, ?, ?, ?)
`;
db.query(sql, [
messageId,
senderName,
@@ -138,6 +155,7 @@ function handleSendMessage(senderName, data) {
}
return;
}
// 数据库确认写入后,才确认发送并推送给接收者
const senderWs = getConnection(senderName);
if (senderWs) {
@@ -169,36 +187,67 @@ function handleSendMessage(senderName, data) {
});
}
function handleAck(receiverName, data) {
function handleAck(data, ws) {
const messageId = data.messageId;
const senderName = data.senderName;
console.log(
`${receiverName} 收到消息 ${messageId},发送 ACK`
);
// 当前 WebSocket 对应的真实用户
const ackUser = ws.username;
// 找到原发送者
const senderWs = getConnection(senderName);
if (!senderWs) {
console.log(
`${senderName} 当前不在线`
);
if (!messageId) {
console.log("ACK 缺少 messageId");
return;
}
// 把 ACK 转给原发送者
senderWs.send(
JSON.stringify({
type: "ack",
messageId:
messageId
})
);
const sql = `
SELECT sender_name, receiver_name
FROM messages
WHERE message_id = ?
`;
db.query(sql, [messageId], (error, results) => {
if (error) {
console.error("查询消息失败:", error);
return;
}
console.log(
`ACK ${messageId} 已发送给 ${senderName}`
);
if (results.length === 0) {
console.log(`消息 ${messageId} 不存在`);
return;
}
const message = results[0];
// 当前用户必须是这条消息的接收者
if (message.receiver_name !== ackUser) {
console.log(
`${ackUser} 无权确认消息 ${messageId}`
);
return;
}
// 原消息发送者
const originalSender = message.sender_name;
console.log(
`${ackUser} 已收到来自 ${originalSender} 的消息 ${messageId},发送 ACK`
);
const senderWs = getConnection(originalSender);
if (!senderWs) {
console.log(
`${originalSender} 当前不在线`
);
return;
}
senderWs.send(
JSON.stringify({
type: "ack",
messageId: messageId
})
);
console.log(
`ACK ${messageId} 已发送给 ${originalSender}`
);
});
}