【问题标题】:Cannot change room correctly in socket.io无法在 socket.io 中正确更改房间
【发布时间】:2018-02-01 01:01:54
【问题描述】:

我使用 node 和 socket.io 实现了聊天。它有服务器和客户端代码。

chatApp.js

"use strict";
let app = require('express')();
let server = require('http').Server(app);
let io = require('socket.io')(server);

app.get('/', (req, res) => {
  res.sendFile(__dirname + "/logs/chat2.html");
});

io.on("connect", (socket) => {
  // New user
  socket.emit("userSelfNotification", {text: "--SELF-- You joined server"});
  socket.broadcast.emit("newUserNotification", {text: "--BROADCAST-- New user"});
  // Send sms
  socket.on("message", (message) => {
    io.sockets.emit("newMessage", {text: message});
  });
  // Change room
  socket.on("changeRoom", (room) => {
    socket.room = room;
    socket.broadcast.emit("leaveRoom", {text: "--BROADCAST-- user left "});
    socket.join(room);
    socket.in(room).emit("roomChangeNotification", {text: "--ROOM-- You left"});
    io.sockets.in(room).emit("newUserNotification", {text: "--ROOM_ALL-- New user joined"});
  });
});

server.listen(3000);

client.html

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Чат</title>
    <script src="https://code.jquery.com/jquery-3.1.0.min.js" charset="utf-8"></script>
    <script src="http://localhost:3000/socket.io/socket.io.js"></script>
    <script>
      let socket = io('http://localhost:3000/');
      socket.on("userSelfNotification", (message) => {
        $("textarea").val($("textarea").val() + message.text + "\n");
      });
      socket.on("newUserNotification", (message) => {
        $("textarea").val($("textarea").val() + message.text + "\n");
      });
      socket.on("newMessage", (message) => {
        $("textarea").val($("textarea").val() + message.text + "\n");
      });
      socket.on("leaveRoom", (message) => {
        $("textarea").val($("textarea").val() + message.text + "\n");
      });
      socket.on("roomChangeNotification", (message) => {
        $("textarea").val($("textarea").val() + message.text + "\n");
      });
      socket.on("newUserNotification", (message) => {
        $("textarea").val($("textarea").val() + message.text + "\n");
      });
    </script>
</head>
<body>
<textarea name="name" rows="15" cols="50"></textarea>
<p></p>
<input type="text" name="text" size="20">
<button type="button" name="button">Отправить</button>
<button type="button" name="changeRoomButton">Сменить комнату</button>
<script>
  $(document).on('click', 'button', () => {
    let message = $('input').val();
    socket.emit("message", message);
    $('input').val(null);
  });
  $(document).ready(function(){
    $("[name='changeRoomButton']").click(function(){
      $(".test").hide();
      console.log("I work babeee");
      socket.emit("changeRoom", "room");
    });
  });
</script>    
</body>
</html>

主要问题是我无法实现房间更改:即使用户更改了房间,他/她仍然可以写入其他默认房间并从中读取其他消息。此外,两个房间都会发出一些事件。

帮助我了解我的错在哪里,谢谢!

【问题讨论】:

    标签: node.js sockets express socket.io


    【解决方案1】:

    由于一个socket客户端可以订阅多个房间,如果你想让你的客户端一次只能在一个房间里,那么你必须在加入时做一个.leave新的。

    访问客户端订阅的房间名称的实际方法是使用:socket.rooms

    但由于您没有订阅(加入)/取消订阅(离开)多个频道(房间)并且一次只有一个活动房间,您可以致电:socket.leaveAll,然后执行socket.join(room)

    例如,如果您想通知客户端断开连接,您必须在 disconnecting 上执行此操作,因为在 disconnect 上,leaveAll() 已被调用:

    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. 
       */
     });
    

    Socket.IO: How to correctly join and leave rooms

    Socket.IO: Emit Cheat Sheet

    【讨论】:

      【解决方案2】:

      感谢您的回答:每一个似乎都是半正确的,但太抽象了。我通过将“socket.room”重新分配给我希望加入的房间来解决这个难题。这个块解决了问题:

      // Change room
      socket.on("changeRoom", (room) => {
          socket.in(defaultRoom).broadcast.emit("leaveRoom", {text: "--BROADCAST-- User left room"});
          socket.leave(defaultRoom);
          socket.room = room;
          socket.join(room);
          socket.emit("roomChangeNotification", {text: "--ROOM-- You changed room"});
          socket.in(room).broadcast.emit("OnewUserNotification", {text: "--ROOM_ALL-- New user joined"});
        });
      

      所以: 1.我添加了默认房间并自动加入了每个连接到服务器的用户 2. 我添加了将 socket.room 参数从“defaultRoom”重新分配给我的名为“room”的自定义房间的代码。就是这样。

      【讨论】:

      • 那不是很好......每次你换房间socket.leave(defaultRoom);时它总是离开defaultRoom(你在第一次改变时已经离开的那个)并且你并没有真正离开新的你加入的房间,所以如果你要使用这个策略,你需要做socket.room = defaultRoom(连接时),然后在changeRoom事件中你必须修改socket.leave(defaultRoom);socket.leave(socket.room);
      • 就像我在回答中所说的那样使用socket.leaveAll 然后socket.join(room) 会更容易(因为您只希望您的客户一次订阅一个房间)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-06
      • 2014-09-15
      • 2016-04-26
      • 2020-11-23
      • 1970-01-01
      • 2017-02-25
      • 1970-01-01
      相关资源
      最近更新 更多