Node.js/Socket.io聊天室房间分配与欢迎消息问题求助
Node.js+Express+Socket.io随机聊天应用:房间分配与消息问题排查
一、房间分配问题
问题现象
用户已连接服务器,但未按预期随机分配至最多5人的房间,且客户端无法获取房间分配信息(定时器未启动)。
服务器核心代码(server.js)
const express = require('express'); const http = require('http'); const socketIo = require('socket.io'); const moment = require('moment'); const app = express(); const server = http.createServer(app); const io = socketIo(server); const port = process.env.PORT || 3001; let chatRooms = {}; let roomDurations = {}; let connectedUsers = {}; app.use(express.static('public')); app.get('/', (req, res) => { res.sendFile(__dirname + '/public/index.html'); }); io.on('connection', (socket) => { console.log('A user connected'); const roomName = assignUserToRoom(socket.id); socket.join(roomName); connectedUsers[socket.id] = { room: roomName }; console.log(`User ${socket.id} assigned to room ${roomName}`); socket.emit('chat message', { username: 'CommonRoom', text: 'Welcome to CommonRoom! Start chatting with random people from around the world.', timestamp: moment().valueOf(), color: "#000000" }); socket.on('chat message', (data) => { console.log(`Received message in room ${roomName}:`, data); io.to(roomName).emit('chat message', data); }); socket.on('disconnect', () => { console.log(`User ${socket.id} disconnected`); if (connectedUsers[socket.id]) { delete connectedUsers[socket.id]; } removeFromRoom(socket.id, roomName); }); }); function assignUserToRoom(socketId) { for (const room in chatRooms) { if (chatRooms[room].length < 5) { chatRooms[room].push(socketId); return room; } } const newRoom = `room-${Object.keys(chatRooms).length + 1}`; chatRooms[newRoom] = [socketId]; roomDurations[newRoom] = Math.floor(Math.random() * (60 * 60)) + 60; return newRoom; } function removeFromRoom(socketId, roomName) { chatRooms[roomName] = chatRooms[roomName].filter(id => id !== socketId); delete connectedUsers[socketId]; if (chatRooms[roomName].length === 0) { delete chatRooms[roomName]; delete roomDurations[roomName]; } } server.listen(port, () => { console.log(`Server running on http://localhost:${port}`); });
问题原因与修复点
- 非随机分配逻辑:
assignUserToRoom函数按固定顺序遍历房间,用户会优先进入第一个未满房间,不符合随机分配需求。- 修复:打乱房间列表顺序后再遍历:
function assignUserToRoom(socketId) { // 打乱房间顺序实现随机分配 const shuffledRooms = Object.keys(chatRooms).sort(() => Math.random() - 0.5); for (const room of shuffledRooms) { if (chatRooms[room].length < 5) { chatRooms[room].push(socketId); return room; } } const newRoom = `room-${Object.keys(chatRooms).length + 1}`; chatRooms[newRoom] = [socketId]; roomDurations[newRoom] = Math.floor(Math.random() * (60 * 60)) + 60; return newRoom; }
- 修复:打乱房间列表顺序后再遍历:
- 未触发客户端房间分配事件:服务器分配房间后,未向客户端发送
room assigned事件,导致客户端无法启动定时器。- 修复:在
socket.join(roomName)后添加:socket.emit('room assigned', { room: roomName, duration: roomDurations[roomName] });
- 修复:在
- 重复删除用户数据:
disconnect事件已删除connectedUsers[socket.id],removeFromRoom函数中重复执行该操作,属于冗余且可能引发错误。- 修复:删除
removeFromRoom函数中的delete connectedUsers[socket.id];语句。
- 修复:删除
二、欢迎消息未显示问题
问题现象
新用户加入时,服务器发送的CommonRoom欢迎消息未在客户端显示。
客户端核心代码(script.js)
document.addEventListener("DOMContentLoaded", () => { const socket = io(); // Connect to the WebSocket server const messageInput = document.getElementById("message-input"); const sendButton = document.getElementById("send-button"); const chatContainer = document.getElementById("chat-container"); const timerValue = document.getElementById("timer-value"); function appendMessage(username, message, color) { const chatMessage = document.createElement("div"); chatMessage.classList.add("chat-message"); chatMessage.innerHTML = `<span class="username" style="color: ${color};">${username}:</span> ${message}`; chatContainer.appendChild(chatMessage); chatContainer.scrollTop = chatContainer.scrollHeight; } function sendMessage() { const message = messageInput.value.trim(); if (message !== "") { appendMessage("You", message, "#007bff"); socket.emit("chat message", { username: "You", message, color: "#007bff" }); messageInput.value = ""; } } sendButton.addEventListener("click", () => { sendMessage(); }); messageInput.addEventListener("keydown", (event) => { if (event.key === "Enter") { sendMessage(); } }); socket.on("chat message", (data) => { appendMessage(data.username, data.message, data.color); }); socket.on('room assigned', (data) => { console.log(`Assigned to room: ${data.room} with duration ${data.duration}`); startTimer(data.duration); }); function startTimer(duration) { let minutes = Math.floor(duration / 60); let seconds = duration % 60; const timerInterval = setInterval(function() { seconds--; if (seconds < 0) { minutes--; seconds = 59; } timerValue.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`; if (minutes <= 0 && seconds <= 0) { clearInterval(timerInterval); alert('Your chat session has ended.'); window.location.reload(); // Reload the page to start a new chat session } }, 1000); } });
问题原因与修复点
字段不匹配:服务器发送的欢迎消息内容字段为text,但客户端接收时尝试读取data.message,导致无法获取消息内容。
- 修复二选一:
- 修改服务器消息字段为
message:socket.emit('chat message', { username: 'CommonRoom', message: 'Welcome to CommonRoom! Start chatting with random people from around the world.', timestamp: moment().valueOf(), color: "#000000" }); - 客户端兼容
text字段:socket.on("chat message", (data) => { appendMessage(data.username, data.message || data.text, data.color); });
- 修改服务器消息字段为
内容的提问来源于stack exchange,提问作者Teji
相关产品推荐
相关产品推荐

