Flask框架(六)websocket应用
本文介绍Flask中websocket功能,下面用实现“服务端主动向前端推送消息”功能来详细介绍:技术栈如下:前端: Vue2.0 + element-ui后台: Flask一、后端代码实现1、创建websocket# 创建Flask Appapp = create_app(DevelopConfig)# 跨域请求CORS(app, supports_credentials=True)# 创建We
·
本文介绍Flask中websocket功能,下面用实现“服务端主动向前端推送消息”功能来详细介绍:
技术栈如下:
-
前端: Vue2.0 + element-ui
-
后台: Flask
一、后端代码实现
1、创建websocket
# 创建Flask App
app = create_app(DevelopConfig)
# 跨域请求
CORS(app, supports_credentials=True)
# 创建WebSocket,用于服务器主动向web端推送消息,避免web端轮询查询
sockets = Sockets(app)
2、保存websocket连接
定义一个字典ws_dict,保存websocket连接
ws_dict = {}
说明:
- websocket连接对象的地址字符串作为key
- {‘ws’: ws, ‘message’: []}作为值,其中ws是websocket连接对象
- 判断‘message’对应的值不为空就发送消息,发送完成后就清空
3、代码实现
@sockets.route('/echo')
def echo_socket(ws):
key = str(ws).split(' ')[-1].rstrip('>') # 用作服务器给web端推送的标识
if key not in ws_dict:
ws_dict[key] = {'ws': ws, 'message': [{'msg': '测试推送服务端推送websocket消息'+key}]}
while not ws.closed:
message = ws.receive() # 接收到消息
if message is not None:
sendmsg = ws_dict.get(key, {}).get('message')
if sendmsg: # 消息不为空时推送
ws.send(json.dumps(sendmsg[0], ensure_ascii=False)) # 主动给客户端推送消息
ws_dict[key]['message'] = []
# flask启动配置
def start_flask():
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
server = pywsgi.WSGIServer(('0.0.0.0', 5000), app, handler_class=WebSocketHandler)
logging.info('server start')
server.serve_forever()
说明:
- 服务端必须接收到客户端发的消息才能保持该服务运行
- 如果ws.receive()没有接收到客户端发送的消息,那么它会关闭与客户端建立的链接
- 底层解释:Read and return a message from the stream. If
None
is returned, then the socket is considered closed/errored. - 所以客户端只建立连接,不与服务端交互通信,则无法实现自由通信状态。
- 要实现推送消息,只需要往ws_dict里面根据key填充数据,发送完消息后清空数据
二、前端代码实现
1、在main.js中添加如下代码
var gWebSocket = null;
var gWsConn = false;
function isJSONStr(str) {
if (typeof str == 'string') {
try {
var obj=JSON.parse(str);
if(typeof obj == 'object' && obj ){
return true;
}else{
return false;
}
} catch(e) {
console.log('error:'+str+'!!!'+e);
return false;
}
}
return false;
}
function initWebsocket() {
if ("WebSocket" in window) {
if (gWebSocket == null) {
var gWsUrl = `ws://127.0.0.1:5000/echo`;
gWebSocket = new WebSocket(gWsUrl);
}
gWebSocket.onopen = function() {
// Web Socket 已连接上,使用 send() 方法发送数据
console.log("websocket已连接...");
gWsConn = true;
};
gWebSocket.onmessage = function(evt) {
console.log("接收数据:" + evt.data);
if (isJSONStr(evt.data)) {
var jsonObj = JSON.parse(evt.data);
sessionStorage.setItem('wskey', jsonObj['wskey']);
}
};
gWebSocket.onclose = function() {
// 关闭 websocket
console.log("连接已关闭...");
gWebSocket = null;
gWsConn = false;
};
} else {
alert("您的浏览器不支持 WebSocket!");
}
}
var initTimer = setInterval(function() {//定时检测websocket连接
if (!gWsConn) {//初始化websocket
initWebsocket();
console.log('Try to connect server...');
} else {
//window.clearInterval(initTimer);
let username = sessionStorage.getItem('username');
if (username != null) {
gWebSocket.send(JSON.stringify({"username":username}));
}
}
}, 5000);
2、登录成功后保存用户信息
async login() {
if (this.form.username == "" || this.form.password == "") {
this.$message({
message: '请输入用户名和密码',
type: 'warning'
});
} else {
let argc = {
'username': this.form.username,
'password': this.form.password
};
let result = await this.$fetchPost('/login', argc);
if (result.status == 200) {
console.log(result.data);
const { groups, roles, msg, code } = result.data;
console.log(groups, roles, msg, code);
if (result.data.code == '0') {
let groups = '{"首页": [], "业务菜单": ["3D模型", "画图展示", "业务3"], "系统设置": ["用户管理", "系统日志"]}';
let roles = '{"首页": ["读"], "3D模型": ["读", "写"], "业务2": ["读", "写"], "业务3": ["读", "写"], "用户管理": ["读", "写"], "系统日志": ["读", "写"]}';
sessionStorage.setItem('record', this.form.record);
sessionStorage.setItem('username', this.form.username);
this.$store.commit('setData', {
'access_token': this.form.username,
'userInfo': this.form.username,
'groups': this.$isJSONStr(groups) ? JSON.parse(groups) : {},
'roles': this.$isJSONStr(roles) ? JSON.parse(roles) : {},
});
this.$router.push('/home');
this.form.password = '';
} else {
this.$message({
message: result.data.msg,
type: 'warning'
});
}
}
}
}
登录成功后把用户信息保存到sessionStorage里面,=根据sessionStorage里有无用户信息判断是否发送websocket请求。
三、完整教程地址
Flask搭建项目完整教程:Flask+Vue搭建系统
更多推荐
已为社区贡献8条内容
所有评论(0)