Python Flask使用自带的websocket
flask使用socketio的比较多,感觉直接使用socket更简单,下面是介绍如何使用flask_sockets的(不是socketio哦)。
- 一、下载安装模块
1.安装flask:pip install flask
2.安装flask_sockets:pip install flask-sockets
3.安装gevent:pip install gevent
- 二、配置flask
先上完整代码:
from flask import Flask, request
from flask_sockets import Sockets
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
import time,json
app = Flask(__name__)
sockets=Sockets(app)
#服务端ws://127.0.0.1:8080/webSocket
@sockets.route('/webSocket', methods=["POST","GET"])
def webSocket(self): #这个self必须加,不然会报错
lastres=""
if request.environ.get("wsgi.websocket"):
ws=request.environ["wsgi.websocket"]
while 1:
msg={"wsmsg":"message from flask websocket at %s"%(time.strftime("%Y-%m-%d,%H:%M:%S"))}
ws.send(json.dumps(msg)) #网络传输一般都用json字符串格式
time.sleep(1)
return
#客户端,http://127.0.0.1:8080/socketshow
@app.route('/socketshow', methods=["POST","GET"])
def socketshow():
html=""" <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Flask Websocket示例</title>
</head>
<body>
<div>
<h2> Flask websocket example</h2>
<p id="websocketmsg"></p>
</div>
<script type="text/javascript">
var websocket = null;
//判断当前浏览器是否支持WebSocket
if ("WebSocket" in window) {
websocket = new WebSocket("ws://localhost:8080/webSocket"); //这里就是这个服务端了
} else {
alert("websocket连接失败!!刷新页面");
setMessageInnerHTML(JSON.stringify({ error: "连接失败" }));
}
//连接发生错误的回调方法
websocket.onerror = function () {
alert("subject连接失败!!刷新页面");
setMessageInnerHTML(JSON.stringify({ error: "error" }));
};
//连接成功建立的回调方法
websocket.onopen = function (event) {
setMessageInnerHTML(JSON.stringify({ key: "webSocket 连接成功~" }));
};
//接收到消息的回调方法
websocket.onmessage = function (event) {
setMessageInnerHTML(event.data);
};
//连接关闭的回调方法
websocket.onclose = function () {
setMessageInnerHTML("close");
};
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,
// 防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
websocket.close();
};
//将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
var result = JSON.parse(innerHTML);
//console.log(result);
if (result) {
document.getElementById("websocketmsg").innerHTML =result.wsmsg;
}
}
//关闭连接
function closeWebSocket() {
websocket.close();
}
</script>
</body>
</html>
"""
return html
if __name__ == '__main__':
#app.run(host="0.0.0.0",port=8093,debug=True) #外网访问需要开端口+host设置为0.0.0.0
server=pywsgi.WSGIServer(("0.0.0.0",8080),app,handler_class=WebSocketHandler)
print("serving flask socket at 0.0.0.0:8080")
server.serve_forever()
- 三、调bug
运行时flask 1以上的版本客户端连接时会报错,WebsocketMismatch
werkzeug.routing.WebsocketMismatch: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
这个可能是wekzeug检查网址有效性太严格了,可以修改site-packages\werkzeug\routing.py代码,把raise WebsocketMismatch()的触发条件注释掉就可以了。
一般的IDE,比如vscode,pycharm都支持点击报错跳转到出错的文件,很好找的。
可以看到raise WebsocketMismatch()的触发条件是websocket_mismatch为True,那只要把它=True注释掉就可以了,
在werkzeug\routing.py搜索websocket_mismatch,可以找到:
把1999行-2001行 这段注释掉
这样就可以了。
另一个可能的bug:
注意服务端的webSocket函数必须加self,因为WebsocketHandler要用self指向这个实例触发事件。
如果不加self,会报TypeError: webSocket() takes 0 positional arguments but 1 was given
- 四、网页端结果
每秒刷新一次。