如何使用 Flask 和 Socket.io 加入和离开房间的简明示例?
Posted
技术标签:
【中文标题】如何使用 Flask 和 Socket.io 加入和离开房间的简明示例?【英文标题】:Concise example of how to join and leave rooms using Flask and Socket.io? 【发布时间】:2019-05-17 08:48:12 【问题描述】:我正在尝试将 socket.io 与连接到 JS 的 Flask 服务器一起使用。我基本上所有事情都在努力,但我的第一步是让用户可以连接到不同的频道。我的广播消息功能正在运行,但是当我单击其他频道时,消息不会发送到其他频道。我做错了什么?
JS:
document.addEventListener('DOMContentLoaded', ()=>
// Send user back to login page if they didn't sign in
const username = localStorage.getItem('username');
if (username == null)
window.location = "/";
// Switch button active class when clicked
$('.list-group .list-group-item.list-group-item-action').click(function(e)
$('.list-group .list-group-item.list-group-item-action.active').removeClass('active');
var $this = $(this);
if (!$this.hasClass('active'))
$this.addClass('active');
e.preventDefault();
);
// Connect to socket.io
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);
socket.on('connect', () =>
// Automatically connect to general channel
socket.emit('join',"channel": "general", "username":username);
// When a channel is clicked, connect to that channel
document.querySelectorAll('.list-group-item').forEach(function(channel)
channel.onclick = () =>
socket.emit('join',"channel":channel.innerhtml, "username":username);
return false;
);
// When a message is sent, call 'send message' function from server
document.querySelector('#send-message').onsubmit = () =>
const message = document.querySelector('#m').value
socket.emit('send message', 'message': message);
// Clear message form
document.querySelector('#m').value = "";
return false;
;
);
// Callback from server for sending messages
socket.on('broadcast message', data =>
console.log(data);
// Append message to list of messages
const li = document.createElement('li');
li.innerHTML = `$data.message`;
document.querySelector('#messages').append(li);
);
);
Python 烧瓶:
import os
from flask import Flask, render_template, url_for
from flask_socketio import SocketIO, emit, join_room, leave_room
from collections import defaultdict
app = Flask(__name__)
app.config["SECRET_KEY"] = os.getenv("SECRET_KEY")
socketio = SocketIO(app)
messages = defaultdict(list)
channels = ["Programming"]
@app.route("/")
def index():
return render_template("login.html")
@app.route("/chatroom/")
def chatroom():
return render_template("chatroom.html", channels=channels, messages=messages)
@socketio.on("send message")
def message(data):
print(data)
emit("broadcast message", "message": message, broadcast=True)
@socketio.on('join')
def on_join(data):
username = data['username']
channel = data['channel']
join_room(channel)
#send(username + ' has entered the room.', channel=channel)
if __name__ == '__main__':
socketio.run(app)
【问题讨论】:
【参考方案1】:将房间想象成一组驻留在服务器上的用户。当您在“发送消息”中发送消息时,您设置了broadcast=True
,因此它将作为全局消息发送给所有用户,只要他们连接。如果您只想发送给特定房间的用户,则需要在每次发送消息时从客户端指定要将消息发送到哪个房间,如下所示:
// 客户端.js
socket.emit('join', 'channel': channel, ... );
socket.emit('send message', 'message': message, 'channel': channel);
// server.py
@socketio.on("send message")
def message(data):
room = data['channel']
emit('broadcast message', data['message'], room=room)
【讨论】:
我是初学者,请问emit
中的第三个参数room=room
是做什么的,我们如何在客户端使用它。我对整个房间的事情一无所知,send
和 emit
如何处理它。
@KakashiHatake room
是 emit 的可选参数。包含时,它只会将消息发送到该特定房间,并且只有加入该房间的客户端才会收到所述消息。房间是套接字可以加入和离开的任意通道。它可用于将事件广播到客户端的子集。房间是一个仅限服务器的概念(即客户端无权访问它已加入的房间列表)。希望这会有所帮助。【参考方案2】:
我相信第一个答案是正确的。请注意,尽可能避免使用“innerhtml”,尤其是在这种情况下。通过设置innerhtml,用户在消息中写入的任何内容在另一端都将被视为html。这包括脚本标签,这意味着某人可以通过发送恶意消息在其他人的机器上远程运行 javascript。
我建议使用 innerText 或 textContent。这会将消息视为纯文本而不是 html。它们略有不同,因此可能值得研究一下您需要哪一个。
我会这样做作为评论,但我的代表不够高。
tl:dr 使用 textContent 或 innerText 代替 innerhtml。
【讨论】:
以上是关于如何使用 Flask 和 Socket.io 加入和离开房间的简明示例?的主要内容,如果未能解决你的问题,请参考以下文章