Flask-Sockets和Flask-SocketIO之间的主要区别在于前者仅仅将WebSocket协议(通过使用gevent-websocket项目)进行包装,因此它只适用于原生支持WebSocket协议的浏览器,对于那些不支持WebSocket协议的较老的浏览器,就无法使用它了。 Flask-SocketIO则不同,通过前面的介绍,读者应该已经知道了它不仅实现了WebSocket协议,并且对于那些不支持WebSocket协议的旧版浏览器,使用它也能够实现相同的效果。新版旧版的浏览器都能使用他 ,另一个区别是Flask-SocketIO实现了SocketIO Javascript库公开的消息传递协议。 Flask-Sockets只是实现通信通道,发送的是完全取决于应用程序。
Flask-SocketIO还为事件处理程序创建了一个类似flask的常规视图函数的环境,包括创建应用程序和请求上下文。 然而,在文档中会介绍一些重要的例外情形。
#!/usr/bin/env python
# encoding: utf-8
"""
@version: v1.0
@author: W_H_J
@license: Apache Licence
@contact: [email protected]
@software: PyCharm
@file: flask_websocket_server.py
@time: 2019/2/20 17:24
@describe: 基于flask_socketio实现websocket的服务端
同时借助flask的路由实现任务发布调度与 消息接收
"""
import sys
import os
from flask import Flask, request, render_template
from flask_socketio import SocketIO, emit
sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
sys.path.append("..")
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
name_space = '/test' # 命名空间
event_name = 'callback message' # 消息接收对象
client_query = []
@app.route('/')
def index():
"""加载HTML客户端"""
return render_template('index.html')
@app.route('/push')
def push_once():
"""
客户端发送消息:http://127.0.0.1:5000/push?msg=a
此方式发布消息见最后一篇代码
"""
data = request.args.get("msg")
broadcasted_data = {'data': data}
print('send msg==>', broadcasted_data)
print("clicent_query==>", client_query)
"""
指定客户端方式发送消息,如果需要针对某一客户端发送,则添加room参数: room=client_query[0],
这里指定第一个连接客户端
emit(event_name, broadcasted_data, broadcast=False, namespace=name_space, room=client_query[0])
"""
# 广播方式发送消息
emit(event_name, broadcasted_data, broadcast=True, namespace=name_space)
return 'send msg ok!'
# on('消息订阅对象', '命名空间区分')
@socketio.on('message', namespace=name_space)
def test_message(message):
""" 服务端接收消息 """
print('recevice message', message)
# 回传给客户端消息,也可以选择不回传
emit('callback message', {'data': message}, broadcast=True, namespace=name_space)
@socketio.on('my broadcast event', namespace=name_space)
def test_message_2(message):
print("my response===>", message)
emit('my response', {'data': message}, broadcast=True)
@socketio.on('connect', namespace=name_space)
def test_connect():
# 建立连接 sid:连接对象ID
client_id = request.sid
print('1 connected ==> ', client_id)
client_query.append(client_id)
emit('connect', '%s connect successful!' % client_id, broadcast=True)
@socketio.on('disconnect', namespace=name_space)
def test_disconnect():
# 连接对象关闭 删除对象ID
client_query.remove(request.sid)
print('0 Client disconnected==> ', request.sid)
if __name__ == '__main__':
socketio.run(app, host='0.0.0.0', port=5000, debug=True)
需要在控制台查看返回消息
Receive:
#!/usr/bin/env python
# encoding: utf-8
"""
@version: v1.0
@author: W_H_J
@license: Apache Licence
@contact: [email protected]
@software: PyCharm
@file: test_clicent.py
@time: 2019/2/21 10:31
@describe: 采用 socketio 模块进行消息发布与接收
https://python-socketio.readthedocs.io/en/latest/server.html
"""
import sys
import os
import socketio
sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
sys.path.append("..")
name_space = '/test'
sio = socketio.Client()
@sio.on('connect')
def on_connect():
"""创建连接"""
print('I am connected!')
@sio.on('my message')
def on_message(data):
print('I received a custom message!')
@sio.on('disconnect')
def on_disconnect():
"""关闭连接"""
print('I m disconnected!')
'''
官方文档:
事件回调:
当客户端向服务器发送事件时,它可以选择提供回调函数,作为服务器处理事件的确认方式调用。
虽然这完全由客户端管理,但服务器可以提供要传递给回调函数的值列表,只需从处理函数返回它们:
@sio.on('my event', namespace='/chat')
def my_event_handler(sid, data):
# handle the message
return "OK", 123
同样,服务器可以请求在客户端处理事件后调用回调函数。该socketio.Server.emit()
方法有一个可选callback参数,可以设置为可调用。如果给出了此参数,则在客户端处理完事件后将调用callable,
并且客户端返回的任何值都将作为参数传递给此函数。不建议在向多个客户端广播时使用回调函数,
因为将为接收消息的每个客户端调用一次回调函数。
'''
@sio.on('callback message', namespace=name_space)
def my_event_handler(data):
# 客户端接收服务端的回调消息
print("my receive new msg:", data)
# 接收完消息关闭连接
sio.disconnect()
return "ok!"
# 建立连接对象
sio.connect('http://127.0.0.1:5000')
sio.emit('message', {'test': 'i am test msg!'}, namespace=name_space)
基于flask,flask_socketio
#!/usr/bin/env python
# encoding: utf-8
"""
@version: v1.0
@author: W_H_J
@license: Apache Licence
@contact: [email protected]
@software: PyCharm
@file: clicentMqtt.py
@time: 2019/1/4 11:25
@describe: 发送查询消息请求
"""
import sys
import os
import requests
sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
sys.path.append("..")
def clicent_main(msg):
"""
发布消息
--基于requests客户端单发给服务端,并不接受服务端回传消息
--http://127.0.0.1:5000/push?msg=a
"""
print('0==> send msg: ', msg)
try:
ws = requests.get("http://127.0.0.1:5000/push?msg=%s" % (msg), timeout=5)
print(ws.text)
except Exception as e:
print(e)
if __name__ == '__main__':
data = {'data': "i am test msg!"}
clicent_main(data)