Javascript 为什么即使在客户离开房间并加入另一个房间后,邮件也会发送到所有房间?长颈瓶

Javascript 为什么即使在客户离开房间并加入另一个房间后,邮件也会发送到所有房间?长颈瓶,javascript,python,flask,websocket,flask-socketio,Javascript,Python,Flask,Websocket,Flask Socketio,当客户离开当前房间并加入另一个房间时,他的消息仍然发送到旧房间,我如何使他的消息只显示在当前房间中? leave_room和join_room工作正常,因为它会在用户加入一个房间时通知用户,并通知其他房间的用户他离开了房间,那么为什么会将消息发送到所有房间 服务器端代码: import os from flask import Flask, session, render_template, redirect, url_for, escape, request, flash from flas

当客户离开当前房间并加入另一个房间时,他的消息仍然发送到旧房间,我如何使他的消息只显示在当前房间中? leave_room和join_room工作正常,因为它会在用户加入一个房间时通知用户,并通知其他房间的用户他离开了房间,那么为什么会将消息发送到所有房间

服务器端代码:

import os

from flask import Flask, session, render_template, redirect, url_for, escape, request, flash
from flask_session import Session
from flask_socketio import SocketIO, emit, send, join_room, leave_room
from time import localtime, strftime




app = Flask(__name__)
app.config["SECRET_KEY"] = os.getenv("SECRET_KEY")
socketio = SocketIO(app)

ROOMS = ["General", "Testing", "One More"]

@app.route("/", methods=["GET", "POST"])
def index():
    return render_template("index.html", rooms=ROOMS)



@socketio.on('message')
def message(data):

    # print(f"\n\n{data}\n\n")
    send({'msg': data['msg'], 'username': data['username'], 'time_stamp': strftime('%b-%d %I:%M%p', localtime()), 'room': data['room']}, broadcast=True)


@socketio.on('join')
def on_join(data):
    username = data['username']
    room = data['room']
    join_room(room)
    send({'msg': username + " has joined the " + room + " room."}, room=data['room'])


@socketio.on('leave')
def on_leave(data):
    username = data['username']
    room = data['room']
    leave_room(room)
    send({'msg': username + " has left the " + room + " room."}, room=data['room'])



if __name__ == '__main__':
    socketio.run(app, debug=True)

客户端

document.addEventListener('DOMContentLoaded', () => {
    var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);
    var username = localStorage.getItem("username");
    let active_room = "General";
    joinRoom(active_room);

    if (!username) {
        username = prompt("Please enter username");
        localStorage.setItem("username", username);
    }
    if (username) {
        document.querySelector('#name-of-client').innerHTML = username;
    }

    // send message to the server
    document.querySelector('#send-btn').onclick = () => {
        socket.send({
            'msg': document.querySelector('#input-msg').value,
            'username': username,
            'room': active_room
        });
        document.querySelector('#input-msg').value = '';
    };

    socket.on('message', data => {

        const p = document.createElement('p');
        const span_username = document.createElement('span');
        const span_timestamp = document.createElement('span');
        const br = document.createElement('br');

        if (data.username) {
            span_username.innerHTML = data.username;
            span_timestamp.innerHTML = data.time_stamp;
            p.innerHTML = span_username.outerHTML + br.outerHTML + data.msg + br.outerHTML + span_timestamp.outerHTML + br.outerHTML;
            document.querySelector('#display-msg').append(p);
        } else {
            printSysMsg(data.msg)
        }


    });


    // room selection
    document.querySelectorAll('.select-room').forEach(p => {
        p.onclick = () => {
            let newRoom = p.innerHTML;
            if (newRoom === active_room) {
                msg = `You are alread in the ${active_room} room.`;
                printSysMsg(msg);
            } else {
                leaveRoom(active_room);
                joinRoom(newRoom);
                active_room = newRoom;
            }

        };
    });

    // Leave Rooms
    function leaveRoom(room) {
        socket.emit('leave', {
            'username': username,
            'room': room
        });
    }


    // Join Room
    function joinRoom(room) {

        socket.emit('join', {
            'username': username,
            'room': room
        });

        // Clear Messages
        document.querySelector('#display-msg').innerHTML = "";
    }


    function printSysMsg(msg) {
        const p = document.createElement('p');
        p.innerHTML = msg;
        document.querySelector('#display-msg').append(p);
    }

});

在.js文件中,您有:

let active_room = "General";
joinRoom(active_room);

就在文件的顶部。您的用户每次都将被踢回“常规”。尝试将一些打印语句放在服务器端和console.log语句放在客户端,以仔细检查您所在的聊天室。

您似乎正在使用创建聊天应用程序(我从
printSysMsg()
函数中猜到)

你的问题 我查看了您的代码,发现您在以下套接字事件(
“message”
)中使用了
broadcast=True
):

解决方案 不要广播您的消息事件,请尝试将其限制在房间内:

send({'msg': data['msg'], 'username': data['username'], 'time_stamp': strftime('%b-%d %I:%M%p', localtime()), 'room': data['room']}, room=data["room"])
推理 记住,在官方网站上:

在启用广播选项的情况下发送消息时,所有客户端 已连接到命名空间并接收它,包括发送方

我在以下网站上阅读了名称空间和房间的概念:

在每个名称空间中,还可以定义 套接字可以连接和离开

我假设Flask SocketIO的工作原理与Socket.IO类似。因此,由于您没有为此消息事件指定特定名称空间,因此设置
broadcast=True
意味着“使用了名为“/”的默认全局名称空间”,您的消息将发送到此名称空间中的所有人

我可能是错的,因为我3天前才开始了解这一点,但这意味着您的广播包括您在名称空间“/”中创建的所有房间。因此,
join_-room
leave_-room
将不会有帮助,因为所有的房间仍在同一名称空间下。他们所有人都将收到该消息

send({'msg': data['msg'], 'username': data['username'], 'time_stamp': strftime('%b-%d %I:%M%p', localtime()), 'room': data['room']}, room=data["room"])