Flask-Socketio 部分翻译

待验证

  1. server端emit数据到浏览器,浏览器端收到数据,无法触发emit指定的回调函数。

广播 Broadcasting

以下 socketio 为 SocketIO的一个实例

Broadcast是SocketIO中非常实用的特性,在 send()emit() 中指定 broadcast = True 可以激活这个特性:

@socketio.on('my event')
def handle_my_custom_event(data):
    emit('my response', data, broadcast=True)

当一条消息通过broadcast的方式发送出去时,当前命名空间内的所有连接都会接收到这条消息,包括触发上述代码中 ‘my event’ 事件的连接。若没有使用命名空间,属于默认命名空间的所有连接都会收到消息。注意, broadcast 消息是不会触发回调函数的
上述代码是通过某个连接触发事件后,调用包含该连接上下文的emit函数来发送广播消息的,但某些情况下,服务器应该成为这个广播消息的发送者。
socketio.send() 以及 socketio.emit() 方法可以将消息广播给所有连接。

def some_function():
    socketio.emit('some event', {'data': 42})

值得注意的是,与 sned(),emit() 这两个函数相比, socketio.send(),socketio.emit() 不需要客户端连接的上下文,所以 broadcast = True 是被默认设置的。


房间 Rooms

对于一些应用来说,需要将用户分为不同的组来进行管理。比如聊天室应用,一个用户可以属于多个组,要获取所属的一个或多个组的聊天信息。Flask-SocketIO通过两个函数 join_room 和 leave_room 实现这种分组的概念。

from flask_socketio import join_room, leave_room

@socketio.on('join')
def on_join(data):
    username = data['username']
    room = data['room']
    join_room(room)
    send(username + ' has entered the room.', room=room)

@socketio.on('leave')
def on_leave(data):
    username = data['username']
    room = data['room']
    leave_room(room)
    send(username + ' has left the room.', room=room)

send() 和 emit() 函数接受一个名为 room 的参数,发送消息时指定此参数,可以将消息发送给’存在’在该房间的所有用户。
任何用户(连接)一旦连接成功,都被分配了一个room,该room以 request.sid 命名。一个用户可以加入任何名字的任何room(即不限于已存在的rooms)。当一个用户disconnect后,所有(这个用户加入过的)房间都会移除这个用户的信息。
无需上下文的 socketio.send() 和 socketio.emit() 也接受一个room参数,将消息发送给该room中所有用户。
既然每个用户都属于一个房间,如果想要给某个用户发消息,只要将room参数指定为此用户的 request.sid 即可


连接事件(Connection Events)

Flask-SocketIO 允许在客户端连接以及断开时触发用户自定义事件:

@socketio.on('connect', namespace='/chat')
def test_connect():
    emit('my response', {'data': 'Connected'})

@socketio.on('disconnect', namespace='/chat')
def test_disconnect():
    print('Client disconnected')

如果 connect 事件返回 False,那么此连接将失败,因此可以在这里进行用户认证操作。
值得注意的是,连接事件以及断开连接事件在不同的命名空间有不同的表现。


基于类的命名空间

除了使用装饰器指定回调,还可以使用类来定义同一命名空间的各种事件:

from flask_socketio import Namespace, emit

class MyCustomNamespace(Namespace):
    def on_connect(self):
        pass

    def on_disconnect(self):
        pass

    def on_my_event(self, data):
        emit('my_response', data)

socketio.on_namespace(MyCustomNamespace('/test'))

As a convenience to methods defined in a class-based namespace, the namespace instance includes versions of several of the methods in the flask_socketio.SocketIO class that default to the proper namespace when the namespace argument is not given.

使用这种方式处理事件的话,服务端接收到事件后,会映射到以 on_ 开头的同名函数,比如浏览器传来的是 my_event, 那么服务端调用的即 on_my_event 函数; 如果没有对应的处理函数,事件就会被忽略。(注意函数名不允许出现非法字符)
如果基于类的处理方法和基于装饰器的方法同时存在,则仅有基于装饰器的方法会被调用。


使用Flask的上下文

SocketIO事件的处理函数和flask的路由处理函数有明显的区别,在SocketIO事件处理程序中,什么能做什么不能做往往容易引起一些困惑。主要区别在于,一个客户端连接产生的所有SocketIO相关事件,都会发生在一个单独的长期存在的连接中。
尽管存在这些区别,Flask-SocketIO依旧希望SocketIO事件的运行环境与普通的HTTP连接请求尽可能的相似,以简化SocketIO事件的处理方式。以下将陈述一些最佳实践:
1. 应用上下文往往是在事件请求触发之前被推入栈,以便于在处理函数中使用 current_appg 变量。
2. 请求上下文往往也是在请求触发之前被推入栈,以便于在处理函数中使用 requestsession 变量。但是,Websocket触发的事件是不会引起单独的请求的,所以上述情况不会在此时发生。因此,引发Websocket连接的请求的请求上下文将在此连接的整个生命周期存在,被所有触发的事件使用。
3. request 这个全局变量将拥有额外的变量 sid,此变量的值是每个连接独一无二的session ID。这个值也被用作每个客户端连接的初始房间号。
4. request 这个全局变量将拥有额外的变量 namespaceevent ,值是当前处理的命名空间和所触发的事件的参数。 event 变量类型为字典,拥有 messageargs 的key。
5. session 这个全局变量在SocketIO中的表现与在普通的HTTP请求中的表现是不同的。在SocketIO连接建立后,一份用户session的拷贝能够被该连接上下文触发的事件处理函数所使用。如果SocketIO注册的处理函数修改了此session变量,这个被修改过的session会被保存,并能够被将来触发的回调函数使用,与此同时,普通的HTTP请求处理函数不会察觉到这个变化。Effectively, when a SocketIO handler modifies the session, a “fork” of the session is created exclusively for these handlers. The technical reason for this limitation is that to save the user session a cookie needs to be sent to the client, and that requires HTTP request and response, which do not exist in a SocketIO connection. When using server-side sessions such as those provided by the Flask-Session or Flask-KVSession extensions, changes made to the session in HTTP route handlers can be seen by SocketIO handlers, as long as the session is not modified in the SocketIO handlers.
6. before_requestafter_request 的钩子对于SocketIO的事件是无效的。
7. SocketIO的处理函数可以使用自定义的装饰器,但是大多数Flask的装饰器往往不适合SocketIO处理函数,因为在SocketIO连接中不存在Response对象的概念。


认证

获取用户身份是一个应用的常见需求,传统的基于表单和HTTP请求的机制在SocketIO连接中显然不再适用,因为根本没有用到HTTP请求和HTTP响应的地方。如果真的有这个必要,应用可以通过SocketIO的message方式,在页面点击提交后发送自定义的登陆表单到服务端进行验证。
但是多数情况下,建立SocketIO连接之前,使用传统的认证方式相对而言似乎更加方便。用户的身份可以被记录在 session或是cookie中,在SocketIO连接建立后那些信息也将被SocketIO的处理函数所使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值