2014-11-04 112 views
1

在我建立的网站Flask,人们可以互相发送PMs。当用户收到pm时,我现在想要实现一个类似于StackOverflow的通知。由于SO使用websocket实现了这个功能,所以我开始使用this tutorial来实现Flask-socketIO(与Socket.io一起使用)的websocket。如何使用websockets使用Flask将消息发送给特定用户?

我下载了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') 

我的评论已经说明了:我怎么发信息给用户谁这条消息是从那里发出的?欢迎所有提示!

[编辑] 继米格尔提示我想创建一个名为作为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' 

回答

6

我怎么能知道是否登录人有网站开通并连接到WebSockets的?

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

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

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

识别用户的最简单方法是将它们放在房间中,然后您可以将消息发送到这些房间。如果您需要单独解决用户问题,那么只需将每个用户放在以用户的昵称或用户名命名的其他房间。管理用户房间的理想场所是connectdisconnect事件处理程序。

不正是你想要的,但我已经写了一个稍微复杂一点的例子,它使用的房间:

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

+1

真棒,从教程自己的主消息! :)感谢您的解释。很高兴听到我可以使用connect事件跟踪自己,这使得它更加灵活。只是关于房间的问题。创造一个房间“便宜”?如果我有成千上万的用户,可以为每个人创建一个空间吗? – kramer65 2014-11-05 10:18:20

+0

正如你在我的第一个问题的编辑中所看到的,我现在写了一个简单的'connect'事件,但是g.object似乎没有在socketio路由中可用。如果我不知道哪个登录用户是尝试连接的用户,您是否知道如何为用户创建空间? – kramer65 2014-11-05 10:50:19

+0

这是正确的,'g'是可用的,但'before_request'处理程序不会运行套接字事件,所以填充'g'的代码没有机会运行,如文档所述。您必须将用户的名称或ID写入会话(可能在用户登录时),因为会话是在套接字事件处理程序中重新创建的。 – Miguel 2014-11-06 02:36:35

相关问题