使用 socket.io 防止向多个房间发送消息
Posted
技术标签:
【中文标题】使用 socket.io 防止向多个房间发送消息【英文标题】:Prevent emiting message to multiple rooms using socket.io 【发布时间】:2018-06-15 21:38:15 【问题描述】:我使用这个单聊天室示例作为参考设置了一个多房间 socket.io / nodeJS 聊天服务器:
https://raw.githubusercontent.com/socketio/socket.io/master/examples/chat/index.js
我使用这个文档将代码从单房间修改为多房间:
https://socket.io/docs/rooms-and-namespaces/
我还修改了代码以在端口 8080 上使用 HTTPS 而不是 HTTP。
我已经实现了多个房间。但是,随着新用户加入不同的聊天室,他们的消息会发送到所有其他聊天室。我想这可能是因为每个人都加入了原来的房间。我的节点控制台日志中的示例:
加入:测试 //user1 加入:测试 //user2 加入:test2 //user3 user1 在测试中说了些什么 user2 正在输入 test user3 在测试中说了些什么
房间应该通过 URL GET 参数动态加入,例如 ?room=room123
这里是 nodeJS index.js 代码。客户端代码与上面的 github 链接中的代码几乎相同。我对节点和 JS 相当陌生。有什么想法吗?
// Setup basic express server
var express = require('express');
var app = express();
var path = require('path');
var fs = require('fs');
var https = require('https');
var url = require('url');
var privateKey = fs.readFileSync('/etc/letsencrypt/live/hostname/privkey.pem', 'utf8');
var certificate = fs.readFileSync('/etc/letsencrypt/live/hostname/fullchain.pem', 'utf8');
var credentials = key: privateKey, cert: certificate;
var server = https.createServer(credentials, app);
var io = require('socket.io')(server);
var port = process.env.PORT || 8080;
/* CONSOLE COLORS */
var GREEN = '\033[0;32m';
var LBLUE = '\033[1;34m';
var BLUE = '\033[0;34m';
var RED = '\033[0;31m';
var YELLOW = '\033[0;33m';
var PURPLE = '\033[0;35m';
var NC = '\033[0m'; // No Color Reset
/* Chatroom Settings */
var numUsers = 0;
var roomID = null;
server.listen(port, function ()
console.log('HTTPS Server listening on port ' + GREEN + '%d' + NC, port);
);
/* Routing */
app.use(express.static(path.join(__dirname, 'public')));
chat();
function chat()
// multiple rooms
io.on('connection', function(socket)
var addedUser = false;
var referer = url.parse(socket.handshake.headers.referer);
var query = (referer.query).split("=");
roomID = query[1];
socket.join(roomID);
/* // attempt to resolve issue of sending messages to all rooms
console.log(socket.adapter.sids);
if(Object.keys(socket.adapter.sids).length < 1)
console.log('Connecting to room:' + roomID);
socket.join(roomID);
*/
console.log("Joining: " + YELLOW + roomID + NC);
//console.log("UUID: " + Object.keys(socket.adapter.nsp.connected)[0]);
//console.log("unique room id:" + Object.keys(socket.adapter.sids));
// when the client emits 'new message', this listens and executes
socket.on('new message', function (data)
// we tell the client to execute 'new message'
socket.to(roomID).emit('new message',
username: socket.username,
message: data
);
console.log(socket.username + ' said something in \t' + YELLOW + roomID + NC);
);
// when the client emits 'add user', this listens and executes
socket.on('add user', function (username)
if (addedUser) return;
// we store the username in the socket session for this client
socket.username = username;
++numUsers;
addedUser = true;
socket.emit('login',
numUsers: numUsers,
);
// echo to room that a person has connected
socket.to(roomID).emit('user joined',
username: socket.username,
numUsers: numUsers
);
);
// when the client emits 'typing', we broadcast it to others
socket.on('typing', function ()
console.log(socket.username + ' is typing in \t' + YELLOW + roomID + NC);
socket.to(roomID).emit('typing',
username: socket.username
);
);
// when the client emits 'stop typing', we broadcast it to others
socket.on('stop typing', function ()
socket.to(roomID).emit('stop typing',
username: socket.username
);
);
// when the user disconnects.. perform this
socket.on('disconnect', function ()
console.log(socket.username + PURPLE + ' disconnected' + NC
+ ' from ' + YELLOW + roomID + NC);
if (addedUser)
--numUsers;
// echo that this client has left
socket.to(roomID).emit('user left',
username: socket.username,
numUsers: numUsers
);
);
);
【问题讨论】:
【参考方案1】:问题最终是由全局“var roomID”变量引起的。一旦我在所有 socket.to(query[1]).emit 函数中使用了 query[1] 变量,它就起作用了。
【讨论】:
【参考方案2】:我在您的代码中看到所有套接字都使用相同的 roomID
变量。他们每个人都需要有自己的roomID
变量。
【讨论】:
roomID 变量是通过 URL 设置的。我不确定你的意思。 您通过roomID
存储房间值,它在chat
函数之外声明
我认为它是一个全局变量。控制台日志每次都显示正确的 roomID。
一个全局变量应该在所有连接之间共享,但是你的连接可能有不同的roomID
对吧?
如果我控制台记录了它正确显示的 roomID,就像在 URL 中一样。你有什么建议我做的不同吗?以上是关于使用 socket.io 防止向多个房间发送消息的主要内容,如果未能解决你的问题,请参考以下文章