软件开发定制Flask:使用SocketIO实现WebSocket与前端Vue进行实时推送(gevent-websocket、flask-socketio、flask不出现running on 127..问题)

前言

软件开发定制本文旨在记录使用框架软件开发定制过程中与前端Vue软件开发定制对接过程中,存在WebSocket软件开发定制总是连接失败导致前端软件开发定制取不到数据的问题。软件开发定制以及在使用WebSocket软件开发定制相关功能的库包gevent-websocket之后,导致运行Flask项目之后,软件开发定制控制台没有显示running on 127.0.0.1:5000 问题、软件开发定制以及没有输出log日志记录的问题、以及总是报错Websocket connection to‘ws://127.0.0.1:5000/socket.io/?EIO=4&transport=websocket’failed:Error during Websocket handshake:Unexpected response code:400’的问题!该篇文章花费了笔者和笔者同学较多精力和时间,转载请说明来源!

如下图所示:只有三行控制台输出的记录、总是报错(该错在网上没有解决方法)等。

技术选型:前端Vue、后端Flask。

核心问题

需要着重注意的是,Flask中有原生的Websocket写法,也有对Websocket封装之后的依赖包SocketIO写法,所以在进行与前端对接的过程中,需要与前端对接好接口标准。在本次项目中,后端最开始用的是封装好WebSocket后的socketio进行编写,而前端使用了原生的websocket-vue写法,导致一直对接不上,获取不到数据。以及所有的报错或者各种bug问题,笔者都推测是跟gevent-websocket这个包有关。

在前端更改为vue-socketio之后,成功解决对接失败问题。(也可以后端改用原生写法,总之两边需要同时使用一个标准。)前端Vue可以参考Vue的文档去看使用哪种写法即可。

Flask的原生WebSocket(flask-sockets)与封装SocketIO

Flask-Sockets和Flask-SocketIO之间的主要区别在于前者仅仅将WebSocket协议(通过使用gevent-websocket项目)进行包装,因此它只适用于原生支持WebSocket协议的浏览器,对于那些不支持WebSocket协议的较老的浏览器,就无法使用它了。

Flask-SocketIO则不同,它不仅实现了WebSocket协议,并且对于那些不支持WebSocket协议的旧版浏览器,使用它也能够实现相同的效果。新版旧版的浏览器都能使用他。可以这么理解,flask把websocket功能封装在了socketio这个新的包里面。

另一个区别是Flask-SocketIO实现了SocketIO Javascript库公开的消息传递协议。
而Flask-Sockets只是实现通信通道,发送的是完全取决于应用程序。

1、Flask-SocketIO(封装写法)

使用SocketIO之前需要导入该包,即pip install flask-socketio。也可以直接在代码中import该包中的两个功能。
即:from flask_socketio import SocketIO, emit。

下面是服务端代码:(关于如何在实战中应用,可以看笔者上一篇关于flask博客中的代码实现,大致思路是使用线程)

from flask import Flask, render_templatefrom flask_socketio import SocketIO, emitapp = Flask(__name__)app.config['SECRET_KEY'] = 'secret!'socketio = SocketIO(app)@app.route('/')def index():    return render_template('index.html')@socketio.on('my event', namespace='/test')def test_message(message):    emit('my response', {'data': message['data']})@socketio.on('my broadcast event', namespace='/test')def test_message(message):    emit('my response', {'data': message['data']}, broadcast=True)@socketio.on('connect', namespace='/test')def test_connect():    emit('my response', {'data': 'Connected'})@socketio.on('disconnect', namespace='/test')def test_disconnect():    print('Client disconnected') if __name__ == '__main__':    socketio.run(app)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

而对于js来说,客户端代码十分简单,直接上代码:(注意是socketio的标准)

$(document).ready(function(){    var socket = io.connect('http://' + document.domain + ':' + location.port + '/test');    //注意如果使用var socket = io.connect(location.protocol + ‘//’ + document.domain.....的写法,这里的protocol是http协议,而不是走的是ws,笔者推测是对ws进行了封装,导致最终走的是http协议。    //上面代码中的/test 就是namespace        socket.on('my response', function(msg) {        $('#log').append('<p>Received: ' + msg.data + '</p>');    });.        $('form#emit').submit(function(event) {        socket.emit('my event', {data: $('#emit_data').val()});        return false;    });        $('form#broadcast').submit(function(event) {        socket.emit('my broadcast event', {data: $('#broadcast_data').val()});        return false;    });});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

2、Flask-Sockets(原生Websocket写法)

服务端:

from flask import Flaskfrom flask_sockets import Socketsimport datetimeimport timeimport randomapp = Flask(__name__)sockets = Sockets(app)@sockets.route('/echo')def echo_socket(ws):    while not ws.closed:        now = datetime.datetime.now().isoformat() + 'Z'        ws.send(now)  #发送数据        time.sleep(1)@app.route('/')def hello():    return 'Hello World!'if __name__ == "__main__":    from gevent import pywsgi    from geventwebsocket.handler import WebSocketHandler    server = pywsgi.WSGIServer(('', 5000), app, handler_class=WebSocketHandler)    print('server start')    server.serve_forever()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

客户端代码:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="https://cdn.bootcss.com/jquery/3.2.0/jquery.js"></script></head><body>    <div id="time" style="width: 300px;height: 50px;background-color: #0C0C0C;    color: white;text-align: center;line-height: 50px;margin-left: 40%;font-size: 20px"></div>    <script>            var ws = new WebSocket("ws://127.0.0.1:5000/echo");  #连接server			//这是websocket的前端原生写法,直接连接ws。            ws.onmessage = function (event) {                content = document.createTextNode(event.data); # 接收数据                $("#time").html(content);            };    </script>    </body></html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

3、Bug 1:控制台输出没有Running on 127.0.0.1以及没有输出日志

在安装了gevent-websocket的这个包之后,会顺带安装gevent这个包,需要注意的是,gevent这个包会导致项目运行之后,控制台不会输出running on这个bug和 没有Log输出日志的bug。

经过笔者查证之后,发现是gevent-websocket这个包太老了,2017年的就已经停止更新了。所以这个包如果使用的话,会顺带导致一些对于新版本的Flask兼容性问题,所以导致了控制台的上述两个Bug存在。

解决方案:删掉gevent、gevent-websocket这两个包,可以下载 simple-websocket这个包来替代这两个包完成功能开发。

解决之后,控制台可以正常显示了。

3、 Bug 2:显示连接错误。

在连接错误之后,推测这种报4的错误(网上全是3的错误),应该是没有安装gevent-websocket这个包,但是安装了之后又会造成第一类bug,所以可以直接安装simple-websocket这个依赖包。

参考文章:https://www.cnblogs.com/wangkun122/articles/9117882.html

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发