使用 socket.io 防止向多个房间发送消息

Prevent emiting message to multiple rooms using socket.io

我设置了一个多房间 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 在测试中说了些什么
用户 2 正在输入测试
user3 在 test

中说了些什么

房间应该通过 URL GET 参数动态加入,例如 ?room=room123

这是 nodeJS index.js 代码。客户端代码与上面的 github link 几乎相同。我对节点和 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  = '3[0;32m';
var LBLUE  = '3[1;34m';
var BLUE   = '3[0;34m';
var RED    = '3[0;31m';
var YELLOW = '3[0;33m';
var PURPLE = '3[0;35m';
var NC     = '3[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
          });
        }
      });

    });

}

我在您的代码中看到所有套接字都使用相同的 roomID 变量。他们每个人都需要有自己的 roomID 变量。

问题最终是由全局 "var roomID" 变量引起的。一旦我在所有 socket.to(query[1]).emit 函数中使用了 query[1] 变量,它就起作用了。