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

时间:2014-11-04 13:23:01

标签: python websocket flask socket.io flask-socketio

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

我按照教程的说法下载了{{3}},我理解其中的代码。但我不明白的是:

  1. 我如何知道登录的人是否打开了网站并连接到websockets?
  2. 如何向该特定用户发送消息?
  3. 所以让我们说我有一个简单的路线,人们可以将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')
    

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

    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'
    

1 个答案:

答案 0 :(得分:7)

  

我如何知道登录的人是否打开网站并连接到websockets?

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

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

  

如何向该特定用户发送消息?

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

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

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