如何在Socket.io房间中向双方展示已连接玩家的用户名
实现房间内两名玩家互相展示用户名的方案
首先,你的项目已经基于passport.js和express-sessions完成了身份认证,要实现实时展示彼此用户名的核心是引入实时通信机制(因为HTTP是请求响应式的,没法主动推送更新),这里推荐用Socket.io来实现,下面是具体的步骤和代码示例:
1. 集成Socket.io并共享Express Session
因为用户的登录信息存在express-sessions里,所以需要让Socket.io能访问到session数据,这样才能拿到当前连接用户的用户名。
服务器端配置(Express + Socket.io)
首先安装依赖:
npm install socket.io express-socket.io-session
然后修改你的Express启动文件:
const express = require('express'); const session = require('express-session'); const passport = require('passport'); const socketIo = require('socket.io'); const sharedSession = require('express-socket.io-session'); const app = express(); const server = require('http').createServer(app); const io = socketIo(server); // 你的session配置(和之前passport用的一致) const sessionMiddleware = session({ secret: 'your-secret-key', resave: false, saveUninitialized: false, // 其他配置比如store等 }); // 应用session和passport中间件 app.use(sessionMiddleware); app.use(passport.initialize()); app.use(passport.session()); // 让Socket.io共享Express的session io.use(sharedSession(sessionMiddleware, { autoSave: true })); // 处理Socket连接 io.on('connection', (socket) => { // 检查用户是否登录(从session中获取) if (!socket.handshake.session.passport?.user) { socket.disconnect(); return; } const currentUser = socket.handshake.session.passport.user; // 这里是你的用户对象,包含username等信息 // 处理创建房间请求 socket.on('createRoom', () => { const roomId = `room-${Date.now()}`; // 生成唯一房间ID socket.join(roomId); // 向当前用户发送房间ID和初始玩家信息 socket.emit('roomJoined', { roomId, players: [currentUser.username] }); }); // 处理加入房间请求 socket.on('joinRoom', (roomId) => { const room = io.sockets.adapter.rooms.get(roomId); // 检查房间是否存在且人数小于2 if (!room || room.size >= 2) { socket.emit('joinFailed', '房间不存在或已满'); return; } socket.join(roomId); // 获取房间内所有玩家的用户名 const players = []; room.forEach(socketId => { const playerSocket = io.sockets.sockets.get(socketId); players.push(playerSocket.handshake.session.passport.user.username); }); players.push(currentUser.username); // 加入当前用户 // 向房间内所有用户推送更新后的玩家列表 io.to(roomId).emit('playersUpdated', { players }); }); // 处理用户断开连接 socket.on('disconnect', () => { // 遍历用户所在的所有房间 socket.rooms.forEach(roomId => { if (roomId !== socket.id) { // 排除用户自身的socket ID房间 const room = io.sockets.adapter.rooms.get(roomId); if (room && room.size > 0) { // 更新房间内玩家列表 const players = []; room.forEach(socketId => { const playerSocket = io.sockets.sockets.get(socketId); if (playerSocket && playerSocket.handshake.session.passport?.user) { players.push(playerSocket.handshake.session.passport.user.username); } }); // 通知剩余玩家更新列表 io.to(roomId).emit('playersUpdated', { players }); } } }); }); }); // 启动服务器 server.listen(3000, () => { console.log('Server running on port 3000'); });
2. 前端页面逻辑
在你的首页(未启动游戏的页面)中,引入Socket.io客户端,并实现创建/加入房间的交互,以及监听玩家列表更新来渲染用户名:
<!DOCTYPE html> <html> <head> <title>游戏首页</title> </head> <body> <div> <button id="createRoomBtn">创建房间</button> <input type="text" id="roomIdInput" placeholder="输入房间ID"> <button id="joinRoomBtn">加入房间</button> </div> <div id="playersContainer"> <h3>房间玩家:</h3> <div id="player1"></div> <div id="player2"></div> </div> <script src="/socket.io/socket.io.js"></script> <script> const socket = io(); // 绑定创建房间按钮事件 document.getElementById('createRoomBtn').addEventListener('click', () => { socket.emit('createRoom'); }); // 绑定加入房间按钮事件 document.getElementById('joinRoomBtn').addEventListener('click', () => { const roomId = document.getElementById('roomIdInput').value.trim(); if (roomId) { socket.emit('joinRoom', roomId); } }); // 监听加入房间成功事件 socket.on('roomJoined', (data) => { console.log('已加入房间:', data.roomId); // 渲染初始玩家(自己) document.getElementById('player1').textContent = `玩家1:${data.players[0]}`; }); // 监听玩家列表更新事件 socket.on('playersUpdated', (data) => { // 根据玩家数量渲染 if (data.players.length >= 1) { document.getElementById('player1').textContent = `玩家1:${data.players[0]}`; } if (data.players.length >= 2) { document.getElementById('player2').textContent = `玩家2:${data.players[1]}`; } else { document.getElementById('player2').textContent = ''; // 清空第二个玩家位置 } }); // 监听加入失败事件 socket.on('joinFailed', (msg) => { alert(msg); }); </script> </body> </html>
3. 关键逻辑说明
- Session共享:通过
express-socket.io-session中间件,让Socket.io能访问到Express的session数据,从而获取当前登录用户的用户名。 - 房间管理:利用Socket.io的房间(Room)功能,将同一房间的用户分组,方便向组内所有用户推送消息。
- 实时同步:当有玩家加入/离开房间时,服务器主动向房间内所有用户推送更新后的玩家列表,前端收到后立即更新DOM,实现实时展示。
你可以根据自己的项目结构调整代码,比如用户对象的字段名(如果你的用户信息不是username,需要对应修改),还有房间ID的生成方式(可以用更友好的ID,比如短字符串)。
内容的提问来源于stack exchange,提问作者roh_dev
相关产品推荐
相关产品推荐

