【问题标题】:Socket.io: How to correctly join and leave roomsSocket.io:如何正确加入和离开房间
【发布时间】:2016-04-26 20:19:15
【问题描述】:

我正在尝试通过构建一组动态创建的聊天室来学习 Socket.io,这些聊天室会在用户进入和离开时发出“连接”和“断开”消息。在查看couple of questions 之后,我整理了一些功能性的东西,但大多数相关的响应来自承认他们已经将答案拼凑在一起的人,我注意到有一个更普遍的 - 也是最近的 -在 Socket.io 存储库上讨论正确的方法(特别是 herehere

由于我是一个新手,我不知道下面的工作是否是一种可接受的做事方式,或者它只是偶然发挥作用,但会导致性能问题或导致过多的听众。如果有一种理想且正式的方式来加入和离开感觉不那么笨重的房间,我很乐意了解它。

客户

var roomId = ChatRoomData._id // comes from a factory


function init() {

    // Make sure the Socket is connected
    if (!Socket.socket) {
        Socket.connect();
    }

    // Sends roomId to server
    Socket.on('connect', function() {
        Socket.emit('room', roomId);
    });

    // Remove the event listener when the controller instance is destroyed
    $scope.$on('$destroy', function () {
        Socket.removeListener('connect');
    });

}

init();

服务器

  io.sockets.once('connection', function(socket){
    socket.on('room', function(room){     // take room variable from client side
      socket.join(room) // and join it

      io.sockets.in(room).emit('message', {      // Emits a status message to the connect room when a socket client is connected
        type: 'status',
        text: 'Is now connected',
        created: Date.now(),
        username: socket.request.user.username
      });

      socket.on('disconnect', function () {   // Emits a status message to the connected room when a socket client is disconnected
        io.sockets.in(room).emit({ 
          type: 'status',
          text: 'disconnected',
          created: Date.now(),
          username: socket.request.user.username
        });  
      })
  });

【问题讨论】:

  • 我的回答有用吗?
  • 第一次看到它现在和很久以前一起破解了一些东西,但这似乎是我想要的:)

标签: node.js sockets socket.io


【解决方案1】:

对于在 2021 年 2 月 1 日之后使用 socket.io 3.1.0 以及希望以后阅读本文的任何人,您可以参考我的示例。我发现 socket.io 文档中有关如何执行此操作的示例不正确。他们声称在断开连接事件中 socket.rooms 是一个对象。虽然 is 使用块容器并且用逗号分隔,但没有密钥对,这意味着它们对 const rooms = Object.keys(socket.rooms) 的演示返回一个空值。它从一个实际上只是一个数组的对象创建一个数组。据我所知,{} 只能用于块语句和对象。出于某种怪癖,NodeJS 将其视为普通数组。我为每个连接事件分配自定义的 4 位数房间。所以我在断开连接事件中让服务器浏览所有房间,如果它遇到长度为 4 的房间名称,它会告诉房间里的每个人房间的大小减少了 1。在客户端,我有一个套接字事件监听器对此进行监控,当它被检测到时,更新一个

innerHTML 属性,以便客户端可以显示连接用户的数量。
//client side code:
socket.on('roomSize', (roomSize) => {
    document.getElementById('clientCount').innerHTML = roomSize + ' clients connected';
});


//Server side code:
io.on("connection", (socket) => {

    socket.on('createRoom', () => {
        let ID = makeID(4)
        while (io.sockets.adapter.rooms.has(ID)) {
            ID = makeID(4)
        }
        socket.join(ID);
        socket.emit('setID', ID);
    });

    socket.on("joinRoom", (room) => {
        socket.join(room);
        let roomSize = io.sockets.adapter.rooms.get(room).size
        io.in(room).emit('roomSize', roomSize);
        socket.emit('roomJoined', room, roomSize);
    });

    socket.on('disconnecting', function() {
        let rooms = socket.rooms;
        rooms.forEach(function(room) {
            if (room.length === 4) {
                let roomSize = io.sockets.adapter.rooms.get(room).size - 1
                io.in(room).emit('roomSize', roomSize);
            }
        });

    });

    function makeID(length) {
        var result = '';
        var characters = '0123456789';
        var charactersLength = characters.length;
        for (var i = 0; i < length; i++) {
            result += characters.charAt(Math.floor(Math.random() * charactersLength));
        }
        return result;
    }
})

【讨论】:

    【解决方案2】:

    这是一个工作方法。

    我在服务器端使用 socketio "socket.io": "^2.3.0"。在客户端是 android

    // SocketIO
    implementation('io.socket:socket.io-client:1.0.0') {
        // excluding org.json which is provided by Android
        exclude group: 'org.json', module: 'json'
    }
    

    以下是对我有用的代码。

    // Join Chat Room
    socket.on('ic_join', function(data) {
    
        // Json Parse String To Access Child Elements
        let messageJson = JSON.parse(data)
        let room1 = messageJson.room1
    
        console.log('======Joined Room========== ')
        console.log(room1)
    
        socket.join(room1, function(err) {
            console.log(io.sockets.adapter.rooms[room1].length);
            console.log(err)
        })
    })
    
    // Leave Chat Room
    socket.on('ic_leave', function(data) {
    
        // Json Parse String To Access Child Elements
        let messageJson = JSON.parse(data)
        let room1 = messageJson.room1
    
        console.log('======Left Room========== ')
        console.log(room1)
    
        socket.leave(room1, function(err) {
            if (typeof io.sockets.adapter.rooms[room1] !== 'undefined' && io.sockets.adapter.rooms[room1] != null) {
                console.log(io.sockets.adapter.rooms[room1].length);
                console.log(err)
            } else{
                console.log("room is deleted")
            }
        })
    })
    

    【讨论】:

      【解决方案3】:

      这就是我通知用户“断开连接的用户”的方式

      socket.on('disconnecting', function(){
              console.log("disconnecting.. ", socket.id)
              notifyFriendOfDisconnect(socket)
          });
      
      function notifyFriendOfDisconnect(socket){
          var rooms = Object.keys(socket.rooms);
          rooms.forEach(function(room){
              socket.to(room).emit('connection left', socket.id + ' has left');
          });
      }
      

      【讨论】:

        【解决方案4】:

        Socket.IO:最近发布的v2.0.3

        关于加入/离开房间[read the docs.]

        加入房间就像socket.join('roomName'一样简单)

        //:JOIN:Client Supplied Room
        socket.on('subscribe',function(room){  
          try{
            console.log('[socket]','join room :',room)
            socket.join(room);
            socket.to(room).emit('user joined', socket.id);
          }catch(e){
            console.log('[error]','join room :',e);
            socket.emit('error','couldnt perform requested action');
          }
        })
        

        然后离开一个房间,简单如socket.leave('roomName');

        //:LEAVE:Client Supplied Room
        socket.on('unsubscribe',function(room){  
          try{
            console.log('[socket]','leave room :', room);
            socket.leave(room);
            socket.to(room).emit('user left', socket.id);
          }catch(e){
            console.log('[error]','leave room :', e);
            socket.emit('error','couldnt perform requested action');
          }
        })
        

        通知房间用户正在断开连接

        Not able to get the list of rooms the client is currently in on disconnect event

        Has been fixed (Add a 'disconnecting' event to access to socket.rooms upon disconnection)

         socket.on('disconnect', function(){(
            /*
              socket.rooms is empty here 
              leaveAll() has already been called
            */
         });
         socket.on('disconnecting', function(){
           // socket.rooms should isn't empty here 
           var rooms = socket.rooms.slice();
           /*
             here you can iterate over the rooms and emit to each
             of those rooms where the disconnecting user was. 
           */
         });
        

        现在发送到特定房间:

        // sending to all clients in 'roomName' room except sender
          socket.to('roomName').emit('event', 'content');
        

        Socket.IO Emit Cheatsheet

        【讨论】:

        • 如果有人已经在房间里怎么办..那么如何提醒其他人有人已经在房间里...
        猜你喜欢
        • 1970-01-01
        • 2019-05-17
        • 2018-05-24
        • 2019-04-11
        • 1970-01-01
        • 1970-01-01
        • 2013-04-01
        • 2017-02-25
        • 1970-01-01
        相关资源
        最近更新 更多