Flask是一个用python开发的网络应用微框架。http://docs.jinkan.org/docs/flask/docs.jinkan.org
而flask-SocketIO 为flask应用提供了一个客户端与服务器之间低延迟的双向通信。客户端应用可以用Javascript,C++,Java,Swift或者其它任意的编程语言的socketio官方库的客户端去和服务端创建一个永久的连接。
from flask import Flask, render_template
from flask_socketio import SocketIO
app = Flask(__name__)
app.configp['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
if __name__ == '__main__':
socketio.run(app)
这就是一个简单的Flask应用。
Flask大量使用装饰器模式,来将用户应用中的各种函数装入Flask框架中。所以学习之前应当对python的装饰器模式的使用熟练掌握。
例如,下面的装饰器socketio.on()实现对接收到的消息'message'的监听,'message'是用户自定义的一个消息种类的名字。也可以改为其他名字。重点是收发要是同一种消息。同时message是用户自定义的数据类。
@socketio.on('message')
def handle_message(message):
print('received message: ' + message)
也可以不使用装饰器语法,而是使用socketio.on_event()代替装饰器来进行消息监听:
def my_function_handler(data):
pass
socketio.on_event('my event', my_function_handler, namespace='/test')
后端的flask-socketio的创建和运行方式如下:
from flask import Flask
from flask_socketio import SocketIO,emit
app = Flask(__name__)
socketio = SocketIO()
socketio.init_app(app)
"""
对app进行一些路由设置
"""
@app.route('/')
def index():
return render_template('test.html')
"""
对socketio进行一些监听设置
"""
if __name__ == '__main__':
socketio.run(app,debug=True,host='0.0.0.0',port=5000)
#这里就不再用app.run而用socketio.run了。socketio.run的参数和app.run也都差不多
使用@app.route('/')装饰器设置路由,@socketio.on设置消息监听。
命名空间namespace使得客户端可以在一个相同的socket上多路复用几个独立的连接。也就是说,同一个物理机可以开启多个进程并使用同一个socket连接到服务器,只需要指定不同的命名空间即可。
@scoketio.on('my event', namespace='/test')
def handle_my_custom_namespace_event(json):
print('received json: ' + str(json))
发送消息:
使用send()和emit()发送消息,它们分别用于无名和命名事件。
@socketio.on('message')
def handle_message(message):
send(message, namespace='/chat')
@socketio.on('my event')
def handle_my_custom_event(json):
emit('my response', json, namespace='/chat')
使用emit时可以指定namespace来指定命名空间。
@socketio.on('my event')
def handle_my_custom_event(json):
emit('my response', ('foo', 'bar', json), namespace='/chat')
发送的消息也可以带有参数'foo'和'bar'。
def ack():
print 'message was received!'
@socketio.on('my event')
def handle_my_custom_event(json):
emit('my response', json, callback=ack)
也可以在发送函数emit()等api中使用回调函数。
@socketio.on('my event')
def handle_my_custom_event(data):
emit('my response', data, broadcast=True)
加入broadcast=True参数可以使得send()和emit()广播消息,所有客户端都会收到它。若指定命名空间,则只有连接到命名空间的客户端会收到消息。
使用room可以实现“群聊”功能。(略)
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'))
使用基于类的命名空间Namespace可以一次性注册消息的监听处理函数,便于管理以及面向对象编程。现在,服务器接收的任何消息都会由on_+消息名为名字的MyCustomNamespace中的成员函数处理。例如my_event消息会由MyCustomNamespace中的on_my_event处理。
socketIO-client是一个基于python实现的socket.io客户端库,这个socket.io原本是一个js的库(flask_socketio也是),github链接:https://github.com/invisibleroads/socketIO-client,它与flask_socketIO的关系是,对于用Flask-SocketIO实现的后端,客户端需要用SocketIO的官方库实现,语言不限。https://flask-socketio.readthedocs.io/en/latest/
大致使用就是这些,现在比较好奇的问题是,收发消息的时候需要考虑tcp的多个包接收处理吗,因为之前在用Python的twisted的时候用datareceived就需要自己对消息做结尾字符,然后作处理,因为twisted的datareceived会在每个tcp包到达的时候进行调用。还有就是socketIO有没有像twisted一样的对于某一个函数执行延时执行的功能,这个功能真的很强大,在差错处理上十分有用。
参考: