You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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}`);
});

问题原因与修复点

  1. 非随机分配逻辑: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;
      }
      
  2. 未触发客户端房间分配事件:服务器分配房间后,未向客户端发送room assigned事件,导致客户端无法启动定时器。
    • 修复:在socket.join(roomName)后添加:
      socket.emit('room assigned', { 
          room: roomName, 
          duration: roomDurations[roomName] 
      });
      
  3. 重复删除用户数据: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,导致无法获取消息内容。

  • 修复二选一:
    1. 修改服务器消息字段为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"
      });
      
    2. 客户端兼容text字段:
      socket.on("chat message", (data) => {
          appendMessage(data.username, data.message || data.text, data.color);
      });
      

内容的提问来源于stack exchange,提问作者Teji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 02:50:24