Flask WebSocket 消息未发出

问题描述 投票:0回答:1

我想使用 Python 和 Flask Web 服务器,使用 WebSocket 将虚拟数据(随机的 4 个字符字符串)流式传输到 HTML 页面上的 div。 Python 和 HTML 的源代码如下。

main7.py

from flask import Flask, render_template
from flask_socketio import SocketIO
import random
import string

app = Flask(__name__)
socketio = SocketIO(app)

@app.route('/')
def index():
    return render_template('index7.html')

def generate_random_chars():
    while True:
        random_chars = ''.join(random.choices(string.ascii_letters + string.digits, k=4))
        socketio.emit('update', random_chars)
        socketio.sleep(2)

if __name__ == '__main__':
    socketio.start_background_task(target=generate_random_chars)
    socketio.run(app, host='localhost', port=5000, debug=True)

index7.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Flask WebSocket Test</title>
</head>
<body>
    <div id="random-chars">Waiting for updates...</div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.0/socket.io.js"></script>
    <script>
        const socket = io();
        socket.on('update', function(data) {
            document.getElementById('random-chars').innerText = data;
        });
    </script>
</body>
</html>

页面的服务没有错误,并且似乎建立了 WebSocket 连接,但此后,网络流量中没有出现任何发出的消息。 Flask 调试输出或 DevTools 控制台也没有错误消息。

 * Restarting with watchdog (inotify)
 * Debugger is active!
 * Debugger PIN: 136-937-281
(210008) wsgi starting up on http://127.0.0.1:5000
(210008) accepted ('127.0.0.1', 49994)
127.0.0.1 - - [29/Aug/2024 19:48:45] "GET / HTTP/1.1" 200 640 0.003211
(210008) accepted ('127.0.0.1', 49998)
127.0.0.1 - - [29/Aug/2024 19:48:45] "GET / HTTP/1.1" 400 293 0.001261
127.0.0.1 - - [29/Aug/2024 19:49:04] "GET / HTTP/1.1" 200 611 0.002471
127.0.0.1 - - [29/Aug/2024 19:49:04] "GET /socket.io/?EIO=4&transport=polling&t=P6V2cR7 HTTP/1.1" 200 278 0.000470
(210008) accepted ('127.0.0.1', 42628)
(210008) accepted ('127.0.0.1', 42634)
127.0.0.1 - - [29/Aug/2024 19:49:04] "POST /socket.io/?EIO=4&transport=polling&t=P6V2cRC&sid=WyHUScU-T8s22PT_AAAA HTTP/1.1" 200 219 0.001391
127.0.0.1 - - [29/Aug/2024 19:49:04] "GET /socket.io/?EIO=4&transport=polling&t=P6V2cRD&sid=WyHUScU-T8s22PT_AAAA HTTP/1.1" 200 213 0.000228
127.0.0.1 - - [29/Aug/2024 19:49:04] "GET /socket.io/?EIO=4&transport=polling&t=P6V2cRM&sid=WyHUScU-T8s22PT_AAAA HTTP/1.1" 200 181 0.000252
127.0.0.1 - - [29/Aug/2024 19:49:48] "GET /socket.io/?EIO=4&transport=websocket&sid=WyHUScU-T8s22PT_AAAA HTTP/1.1" 200 0 43.720072
127.0.0.1 - - [29/Aug/2024 19:49:48] "GET / HTTP/1.1" 200 611 0.001028
127.0.0.1 - - [29/Aug/2024 19:49:48] "GET /socket.io/?...

devtools

任何对问题的见解表示赞赏!

python flask websocket
1个回答
0
投票

解决方案是避免用户 Woodford 指出的竞争条件,特别是仅在建立 WebSocket 连接后才启动发出任务。
下面是修改后的工作代码,在客户端提供额外的网络状态报告:

主.py

from datetime import datetime
import logging
from flask import Flask, render_template
from flask_socketio import SocketIO

app = Flask(__name__)
socketio = SocketIO(app)

# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

@app.route('/')
def index():
    return render_template('index.html')

def generate_time_str():
    while True:
        time_str = str(datetime.now())
        logger.info(f"Emitting: {time_str}")
        socketio.emit('update', time_str)
        socketio.sleep(1)

@socketio.on('connect')
def handle_connect():
    logger.info("Client connected")
    socketio.start_background_task(target=generate_time_str)

if __name__ == '__main__':
    socketio.run(app, host='localhost', port=5000, debug=True)

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Flask WebSocket Test</title>
    <style>
        .error { color: red; }
        .connected { color: green; }
        .disconnected { color: orange; }
    </style>
</head>
<body>
    <div id="server-data"></div>
    <div id="network-status">Connecting to server...</div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.0/socket.io.js"></script>
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const socket = io({
                reconnection: true,
                reconnectionAttempts: Infinity,
                reconnectionDelay: 1000,
                reconnectionDelayMax: 5000,
                timeout: 20000,
            });
            const randomCharsDiv = document.getElementById('server-data');
            const networkStatusDiv = document.getElementById('network-status');
            
            function updateNetworkStatus(message, className) {
                networkStatusDiv.textContent = message;
                networkStatusDiv.className = className;
            }

            socket.on('connect', function() {
                console.log('Connected to server');
                updateNetworkStatus('Connected to server', 'connected');
            });

            socket.on('update', function(data) {
                console.log('Received update:', data);
                randomCharsDiv.textContent = data;
            });

            socket.on('disconnect', function(reason) {
                console.log('Disconnected from server:', reason);
                updateNetworkStatus('Disconnected from server', 'disconnected');
            });

            socket.on('connect_error', function(error) {
                console.error('Connection error:', error);
                updateNetworkStatus('Error connecting to server', 'error');
            });

            socket.on('reconnect_attempt', function(attemptNumber) {
                console.log('Attempting to reconnect:', attemptNumber);
                updateNetworkStatus(`Attempting to reconnect (${attemptNumber})`, 'disconnected');
            });

            socket.on('reconnect', function(attemptNumber) {
                console.log('Reconnected on attempt:', attemptNumber);
                updateNetworkStatus('Reconnected to server', 'connected');
            });

            socket.on('reconnect_error', function(error) {
                console.error('Reconnection error:', error);
                updateNetworkStatus('Error reconnecting to server', 'error');
            });

            socket.on('reconnect_failed', function() {
                console.error('Failed to reconnect');
                updateNetworkStatus('Failed to reconnect to server', 'error');
            });
        });
    </script>
</body>
</html>
© www.soinside.com 2019 - 2024. All rights reserved.