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

 

  •  四、网页端结果

 

 每秒刷新一次。

posted @ 2022-04-09 19:18  科学修行的红客  阅读(5905)  评论(1编辑  收藏  举报