Python中flask-socketio如何向指定用户发送消息?
我知道客户端在向服务器发送连接请求的时候 flask 可以获取 sid...然后怎么办呢....em..请教个各位大神!
Python中flask-socketio如何向指定用户发送消息?
在 server 端你得自己做一个客户端的 map 吧
在Flask-SocketIO中,要向指定用户发送消息,最直接的方式是使用send()或emit()函数时,通过room参数指定用户的会话ID。每个连接的用户都会被自动分配一个唯一的sid(session ID),这个sid在连接建立时可以通过request.sid获取,并且服务器会自动为每个sid创建一个同名的房间(room)。
下面是一个完整的示例,展示了如何向特定用户发送消息:
from flask import Flask, request
from flask_socketio import SocketIO, emit, send
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'
socketio = SocketIO(app, cors_allowed_origins="*")
# 存储用户ID和其socketio会话ID(sid)的映射
# 注意:生产环境中应使用更持久化的存储,如Redis
user_sid_map = {}
@socketio.on('connect')
def handle_connect():
"""客户端连接时触发"""
# 假设客户端连接时发送了其用户ID
# 在实际应用中,这通常需要在认证后完成
user_id = request.args.get('user_id')
if user_id:
user_sid_map[user_id] = request.sid
print(f"用户 {user_id} 已连接, sid: {request.sid}")
@socketio.on('private_message')
def handle_private_message(data):
"""处理发送给特定用户的私信"""
target_user_id = data.get('to_user_id')
message = data.get('message')
if not target_user_id or not message:
return
# 查找目标用户的会话ID
target_sid = user_sid_map.get(target_user_id)
if target_sid:
# 向指定sid(即房间)发送消息
# 使用emit发送带事件名的消息
socketio.emit('new_private_message',
{'message': message, 'from': data.get('from_user_id')},
room=target_sid)
# 或者使用send发送无事件名的消息
# socketio.send(message, room=target_sid)
print(f"消息已发送给用户 {target_user_id}")
else:
print(f"用户 {target_user_id} 未连接")
@socketio.on('disconnect')
def handle_disconnect():
"""客户端断开连接时触发"""
# 从映射中移除断开连接的用户
user_id_to_remove = None
for uid, sid in user_sid_map.items():
if sid == request.sid:
user_id_to_remove = uid
break
if user_id_to_remove:
del user_sid_map[user_id_to_remove]
print(f"用户 {user_id_to_remove} 已断开连接")
if __name__ == '__main__':
socketio.run(app, debug=True)
关键点说明:
-
用户标识映射:你需要建立一个从你的业务用户ID到SocketIO会话ID(
sid)的映射。这个映射通常在connect事件中建立,在disconnect事件中清理。示例中使用了内存字典,但在生产环境(尤其是多进程/多服务器部署)中,应该使用像Redis这样的外部存储。 -
发送消息:要向特定用户发送消息,只需获取该用户对应的
sid,然后将其作为room参数传递给emit()或send()函数。因为每个sid自动就是一个房间名。 -
客户端代码示例(HTML/JS):
<script src="https://cdn.socket.io/4.5.0/socket.io.min.js"></script>
<script>
// 连接时带上用户ID
const userId = "user_123"; // 实际应从登录状态获取
const socket = io.connect('http://localhost:5000?user_id=' + userId);
// 监听私信
socket.on('new_private_message', function(data) {
console.log('收到私信:', data);
});
// 发送私信给另一个用户
function sendPrivateMessage() {
socket.emit('private_message', {
to_user_id: 'user_456',
message: '你好!',
from_user_id: userId
});
}
</script>
一句话总结:用user_id到sid的映射,通过sid作为房间名调用emit(message, room=target_sid)即可定向发送。
大神可不可以具体一点,小白有点懵逼…
连接时给他们 join(自己 userId) 的 room
记录用户连接时的 sessionid
自己在数据库(redis, mysql, mongodb)存一下 userId 和 sessionId 的绑定关系,然后
socketio.emit(“message”, {‘data’: data}, room=sid])
感谢楼上的各位! emit(…,room=sid) 解决我的问题!👍

