Skip to main content
 首页 » 编程设计

python之如何使用 websockets 通过 Flask 向特定用户发送消息

2025年05月04日34kerrycode

在我用 Flask 构建的网站中, 人们可以互相发送 PM。当用户收到 pm 时,我现在想实现一个类似于 StackOverflow 的通知。由于 SO 使用 websockets 实现了这一点,我开始使用 websockets this tutorial关于实现Flask-socketIO (适用于 Socket.io )。

我下载了the example正如本教程所做的那样,我理解其中的代码。然而,我不明白的是:

  1. 我如何知道登录的人是否打开了网站并连接到 websockets?
  2. 如何向该特定用户发送消息?

假设我有一个简单的路由,人们可以在其中向另一个用户发送 PM:

@app.route('/admin/pm', methods=['GET', 'POST']) 
@login_required 
def pms(): 
    if request.method == 'POST': 
        savePM(g.user.id, request.form['toUserId'], request.form['text']) 
        # How do I emit a message here to the user to whom this message is sent? 
    return render_template('sendPM.html') 

我的评论已经说明了这一点:我如何向从那里发送此消息的用户发送消息?欢迎所有提示!

[编辑] 根据 Miguel 的提示,我想创建一个名为 user.id 的房间,因此我现在创建了以下连接和断开连接事件:

@socketio.on('connect', namespace='/test') 
@login_required 
def websocketConnect(): 
    join_room(g.user.id) 
    emit('my response', {'data': 'Connected'}, room=g.user.id) 
 
@socketio.on('disconnect', namespace='/test') 
@login_required 
def websocketDisconnect(): 
    leave_room(g.user.id) 
    print('Client disconnected') 

但是在连接后我得到了下面的堆栈跟踪。 g对象不是用socketio路由创建的吗?

Traceback (most recent call last): 
  File "/Library/Python/2.7/site-packages/gevent/greenlet.py", line 327, in run 
    result = self._run(*self.args, **self.kwargs) 
  File "/Library/Python/2.7/site-packages/socketio/virtsocket.py", line 403, in _receiver_loop 
    retval = pkt_ns.process_packet(pkt) 
  File "/Library/Python/2.7/site-packages/socketio/namespace.py", line 164, in process_packet 
    return self.call_method_with_acl('recv_connect', packet) 
  File "/Library/Python/2.7/site-packages/socketio/namespace.py", line 240, in call_method_with_acl 
    return self.call_method(method_name, packet, *args) 
  File "/Library/Python/2.7/site-packages/socketio/namespace.py", line 282, in call_method 
    return method(*args) 
  File "/Library/Python/2.7/site-packages/flask_socketio/__init__.py", line 79, in recv_connect 
    self.socketio._dispatch_message(app, self, 'connect') 
  File "/Library/Python/2.7/site-packages/flask_socketio/__init__.py", line 137, in _dispatch_message 
    ret = self.messages[namespace.ns_name][message](*args) 
  File "/Library/Python/2.7/site-packages/flask_login.py", line 758, in decorated_view 
    return func(*args, **kwargs) 
  File "/Users/kramer65/repos/vg/app/views/webviews.py", line 418, in websocketConnect 
    join_room(g.user.id) 
  File "/Library/Python/2.7/site-packages/werkzeug/local.py", line 338, in __getattr__ 
    return getattr(self._get_current_object(), name) 
AttributeError: '_AppCtxGlobals' object has no attribute 'user' 

请您参考如下方法:

How can I know whether a logged in person has the website open and is connected to websockets?

由您来跟踪这一点。当用户连接到套接字端点时,您将获得 connect 事件,您可以在此处将用户注册为已连接。 connect 事件处理程序可以访问 session,因此如果登录用户将他们的 id 或昵称写入 session ,您可以在 socket connect 处理程序中访问它。

此外,当用户离开时,您将收到一个disconnect 事件。

How can I send a message to that specific user?

识别用户的最简单方法是将他们放在房间中,然后您可以向这些房间发送消息。如果您需要单独处理用户,则只需将每个用户放在不同的房间,以用户的昵称或 ID 命名。再次,connect 和 disconnect 事件处理程序是管理用户房间的最佳位置。

不完全是你想要的,但我写了一个使用房间的稍微复杂的例子:

https://github.com/miguelgrinberg/Flask-SocketIO-Chat