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

 

  •  四、網頁端結果

 

 每秒刷新一次。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM