<ul>很抱歉,第二部分来得太迟。不过,我向读者朋友们保证:在2016年结束前,一定会将完整的翻译呈现给大家。
第二部分将进一步介绍flask-SocketIO的一些使用的特性,包括房间,基于类的命名空间等,这些特性的使用,将会给你的flask app带来一些小惊喜。</ul>
6.广播
SocketIO另外一个非常有用的特性就是广播消息。Flask-SocketIO中,只要将broadcast = True
这个可选参数加到send()和emit()中即可:
@socketio.on('my event')
def handle_my_custom_event(data):
emit('my response', data, broadcast=True)
当一个消息以广播选项被开启的情况下被发出的时候,连接到这个命名空间的所有客户端都会收到这个消息。注意:广播的消息将不会被回调。
所有的例子表明,直到这个节点服务器才回复客户端发出的这个活动。但是另外的应用中,服务器需要成为消息的发起者。对于起源于服务器的活动而言,这个有利于发送通知到客户端,比如在后台线程中。socketio.send()和socketio.emit()方法可以用来对所有的连接进行广播。
def some_function():
socketio.emit('some event', {'data': 42})
注意:通过对send()和emit()的上下文的感知,socketio.send()和socketio.emit()不是相同的函数。同样需要注意的是:以上的用法是没有客户端内容,所以假定broadcast=True,并且需要被具体化。
7.房间
在许多应用中,有必要将用户划分为可以一并处理的几个子集。最好的例子是,一个包含多个房间的聊天应用,当用户收到他所在的房间的消息,而不会收到其他人所在房间的消息。Flask-SocketIO支持通过join_room()和leave_room()函数来支持房间的概念:
from flask_socketio import join_room, leave_room
@socketio.on('join')
def on_join(data):
uername=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作为一个参数,将消息广播到所有在给定房间里的客户端。
所有连接(到服务器)的客户端都被分配到一个房间,并且以连接的会话编号(session ID)命名这个房间的名称,这个会话编号由request.sid获得。一个既定的客户端可以加入任何一个房间,这个房间的名称可以是任何名称。当一个客户端终止(与服务器的)连接,它将会从原来所在的房间里除名。这两个上下文无关的函数socketio.send()和socketio.emit()也会接受参数room,把消息广播到这个房间里的所有客户端。
一旦所有的客户端被分配到一个自己的房间,为了将消息发送到一个唯一的客户端,会话编号可以作为参数room的值。
8.连接活动
Flask-SocketIO同样支持连接和断开的活动。接下来的例子将会展示怎样为他们注册一个处理函数:
@socketio.on('connect', namespace='/chat')
def test_connect():
emit('my response', {'data': 'Connected'})
@socketio.on('disconnected', namespace='/chat')
def test_disconnected():
print('Client disconnected')
连接活动处理处理函数可以选择性地返回一个False去拒绝这个连接。这是为了在这一点上进行身份认证。
注意:连接和断开活动可以在各自使用的命名空间内独立地发送。
9.基于类的命名空间
以上描述的作为基于装饰器的活动处理函数的替代,属于命名空间的活动处理函数可以被创造成一个类的方法。Flask_socketio.Namespace提供了一个基于类的方法来创造命名空间。
from flask_socketio import Namespace, emit
class MyCustomNamespace(Namespace):
def on_conect():
pass
def on_disconnect():
pass
def on_my_event(data):
emit('my_response', data)
socket.on_namespace(MyCustomNamespace('/test'))
使用一个基于类的命名空间时,所有服务器接收到的活动将会被分配到一个方法,该方法的活动名称是以on_为前缀的活动。例如,名称为my_event的活动,将会由on_my_event函数来处理。如果一个接收到的活动在命名空间类中没有与之相匹配的处理方法。这个活动将会被忽略。所有在基于类的命名空间内的活动必须使用具有合法的方法名称的单词。
作为一个定义基于类的命名空间的简便方法,这个命名空间实例包括了几个版本的flask_socketio.SocketIO类,并且他们默认的命名空间参数并没有给出。
如果一个活动同时具有在基于类的命名空间里的处理函数和基于装饰器的处理函数,只有装饰器函数会被调用。
10.错误处理
Flask-SocketIO也可以处理异常:
@socketio.on_error() # handles the dafault namespace
def error_handler(e):
pass
@socketio.on_error('/chat') # handles the '/chat' namespace
def error_handler_chat(e):
pass
@socketio.on_error_default # handles all namespaces without an explicit error handler
def default_error_handler(e):
pass
错误处理函数将异常对象作为一个参数
这个消息和数据参数作为当前的请求将会被察觉request.event变量察觉,这有利于外部活动处理函数的错误日志和调试
from flask import request
@socketio.on("my error event")
def on_my_event(data):
raise RuntimeError()
@socket.on_error_default
def default_error_handler(e):
print(request.event["message"]) # "my error event"
print(request.event["args"]) # (data,)