最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Use Flask-SocketIO to send messages continuously - Stack Overflow

programmeradmin1浏览0评论

I would like to build an application to monitor files on my local computer through the browser. I have written a minimalistic example to illustrate this.

The frontend should be able to request messages from the backend on events. In my example below, I am calling these "standard messages". They are triggered in the frontend by a button click and a fetch call, and handled in the backend by a route.

The backend should also send messages every 5 seconds. I am calling these "continuous messages" and I am trying to send them using Flask-SocketIO. They are sent by the backend with socketio start_background_task and emit, and are received by the frontend with socket.on().

The "standard messages" part works fine if I comment the socketio part (and replace socketio.run with app.run). But when I uncomment the socketio part to have "continuous messages", the communication fails. The backend doesn't receive the "standard messages" calls, and the frontend doesn't receive the "continuous messages".

It looks like I am not writing the socketio part correctly. What do I need to add so that both messages type work correctly?

Backend

import time
import logging

from flask import Flask
from flask_cors import CORS
from flask_socketio import SocketIO

app = Flask(__name__)
CORS(app)

logging.basicConfig(level=logging.DEBUG)

# Continuous messages ##########################################
socketio = SocketIO(app, cors_allowed_origins="*", logger=True, engineio_logger=True)

@socketio.on('connect')
def handle_connect():
    print('Client connected')
    socketio.start_background_task(send_continuous_messages)

def send_continuous_messages():
    while True:
        print("Backend sends a continuous message")
        socketio.emit("continuous_message", {"data": "New continuous message"})
        time.sleep(5)
################################################################

@app.route("/standard-message", methods=["GET"])
def generate_standard_message():
    print("Backend sends a standard message")
    return {"data": "New standard message"}

if __name__ == "__main__":
    print("Starting app")
    socketio.run(app, debug=True)

Frontend

const myButton = document.getElementById('my-button');
const BASE_URL = "http://localhost:5000";

localStorage.debug = '*';

// Continuous messages #########################################
const socket = io(BASE_URL);

socket.on('connect', () => {
    console.log('WebSocket connected');
});

socket.on('disconnect', () => {
    console.log('WebSocket disconnected');
});

socket.on('continuous_message', (data) => {
    console.log('Frontend received a continuous message:', data);
});
// #############################################################

async function receiveStandardMessage() {
    console.log('Frontend is requesting a standard message');
    const response = await fetch(`${BASE_URL}/standard-message`);
    const data = await response.json();
    console.log('Frontend received a standard message:', data);
}

myButton.addEventListener('click', receiveStandardMessage);

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My app</title>
    <script src=".0.0/socket.io.min.js"></script>
</head>
<body>
    <div id="app">
        <button id="my-button">Send standard message</button>
    </div>
    <script src="app.js"></script>
</body>
</html>

Server logs

Server initialized for eventlet.
INFO:engineio.server:Server initialized for eventlet.
Starting app
INFO:werkzeug: * Restarting with stat
Server initialized for eventlet.
INFO:engineio.server:Server initialized for eventlet.
Starting app
WARNING:werkzeug: * Debugger is active!
INFO:werkzeug: * Debugger PIN: 141-243-050
(6318) wsgi starting up on http://127.0.0.1:5000
(6318) accepted ('127.0.0.1', 52009)
GotWW8oC3BEz4J3jAAAA: Sending packet OPEN data {'sid': 'GotWW8oC3BEz4J3jAAAA', 'upgrades': ['websocket'], 'pingTimeout': 20000, 'pingInterval': 25000, 'maxPayload': 1000000}
INFO:engineio.server:GotWW8oC3BEz4J3jAAAA: Sending packet OPEN data {'sid': 'GotWW8oC3BEz4J3jAAAA', 'upgrades': ['websocket'], 'pingTimeout': 20000, 'pingInterval': 25000, 'maxPayload': 1000000}
127.0.0.1 - - [06/Mar/2025 17:40:49] "GET /socket.io/?EIO=4&transport=polling&t=PLiLCOB HTTP/1.1" 200 335 0.001486
GotWW8oC3BEz4J3jAAAA: Received packet MESSAGE data 0
INFO:engineio.server:GotWW8oC3BEz4J3jAAAA: Received packet MESSAGE data 0
Client connected
GotWW8oC3BEz4J3jAAAA: Sending packet MESSAGE data 0{"sid":"w_DlD83bH5OBQRbiAAAB"}
INFO:engineio.server:GotWW8oC3BEz4J3jAAAA: Sending packet MESSAGE data 0{"sid":"w_DlD83bH5OBQRbiAAAB"}
127.0.0.1 - - [06/Mar/2025 17:40:50] "POST /socket.io/?EIO=4&transport=polling&t=PLiLCOy&sid=GotWW8oC3BEz4J3jAAAA HTTP/1.1" 200 202 0.003777
Backend sends a continuous message
emitting event "continuous_message" to all [/]
INFO:socketio.server:emitting event "continuous_message" to all [/]
GotWW8oC3BEz4J3jAAAA: Sending packet MESSAGE data 2["continuous_message",{"data":"New continuous message"}]
INFO:engineio.server:GotWW8oC3BEz4J3jAAAA: Sending packet MESSAGE data 2["continuous_message",{"data":"New continuous message"}]
Backend sends a continuous message
emitting event "continuous_message" to all [/]
INFO:socketio.server:emitting event "continuous_message" to all [/]
GotWW8oC3BEz4J3jAAAA: Sending packet MESSAGE data 2["continuous_message",{"data":"New continuous message"}]
INFO:engineio.server:GotWW8oC3BEz4J3jAAAA: Sending packet MESSAGE data 2["continuous_message",{"data":"New continuous message"}]

Client logs

Frontend is requesting a standard message
Firefox can’t establish a connection to the server at ws://localhost:5000/socket.io/?EIO=4&transport=websocket&sid=GotWW8oC3BEz4J3jAAAA.
WebSocket disconnected

I would like to build an application to monitor files on my local computer through the browser. I have written a minimalistic example to illustrate this.

The frontend should be able to request messages from the backend on events. In my example below, I am calling these "standard messages". They are triggered in the frontend by a button click and a fetch call, and handled in the backend by a route.

The backend should also send messages every 5 seconds. I am calling these "continuous messages" and I am trying to send them using Flask-SocketIO. They are sent by the backend with socketio start_background_task and emit, and are received by the frontend with socket.on().

The "standard messages" part works fine if I comment the socketio part (and replace socketio.run with app.run). But when I uncomment the socketio part to have "continuous messages", the communication fails. The backend doesn't receive the "standard messages" calls, and the frontend doesn't receive the "continuous messages".

It looks like I am not writing the socketio part correctly. What do I need to add so that both messages type work correctly?

Backend

import time
import logging

from flask import Flask
from flask_cors import CORS
from flask_socketio import SocketIO

app = Flask(__name__)
CORS(app)

logging.basicConfig(level=logging.DEBUG)

# Continuous messages ##########################################
socketio = SocketIO(app, cors_allowed_origins="*", logger=True, engineio_logger=True)

@socketio.on('connect')
def handle_connect():
    print('Client connected')
    socketio.start_background_task(send_continuous_messages)

def send_continuous_messages():
    while True:
        print("Backend sends a continuous message")
        socketio.emit("continuous_message", {"data": "New continuous message"})
        time.sleep(5)
################################################################

@app.route("/standard-message", methods=["GET"])
def generate_standard_message():
    print("Backend sends a standard message")
    return {"data": "New standard message"}

if __name__ == "__main__":
    print("Starting app")
    socketio.run(app, debug=True)

Frontend

const myButton = document.getElementById('my-button');
const BASE_URL = "http://localhost:5000";

localStorage.debug = '*';

// Continuous messages #########################################
const socket = io(BASE_URL);

socket.on('connect', () => {
    console.log('WebSocket connected');
});

socket.on('disconnect', () => {
    console.log('WebSocket disconnected');
});

socket.on('continuous_message', (data) => {
    console.log('Frontend received a continuous message:', data);
});
// #############################################################

async function receiveStandardMessage() {
    console.log('Frontend is requesting a standard message');
    const response = await fetch(`${BASE_URL}/standard-message`);
    const data = await response.json();
    console.log('Frontend received a standard message:', data);
}

myButton.addEventListener('click', receiveStandardMessage);

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My app</title>
    <script src="https://cdn.socket.io/4.0.0/socket.io.min.js"></script>
</head>
<body>
    <div id="app">
        <button id="my-button">Send standard message</button>
    </div>
    <script src="app.js"></script>
</body>
</html>

Server logs

Server initialized for eventlet.
INFO:engineio.server:Server initialized for eventlet.
Starting app
INFO:werkzeug: * Restarting with stat
Server initialized for eventlet.
INFO:engineio.server:Server initialized for eventlet.
Starting app
WARNING:werkzeug: * Debugger is active!
INFO:werkzeug: * Debugger PIN: 141-243-050
(6318) wsgi starting up on http://127.0.0.1:5000
(6318) accepted ('127.0.0.1', 52009)
GotWW8oC3BEz4J3jAAAA: Sending packet OPEN data {'sid': 'GotWW8oC3BEz4J3jAAAA', 'upgrades': ['websocket'], 'pingTimeout': 20000, 'pingInterval': 25000, 'maxPayload': 1000000}
INFO:engineio.server:GotWW8oC3BEz4J3jAAAA: Sending packet OPEN data {'sid': 'GotWW8oC3BEz4J3jAAAA', 'upgrades': ['websocket'], 'pingTimeout': 20000, 'pingInterval': 25000, 'maxPayload': 1000000}
127.0.0.1 - - [06/Mar/2025 17:40:49] "GET /socket.io/?EIO=4&transport=polling&t=PLiLCOB HTTP/1.1" 200 335 0.001486
GotWW8oC3BEz4J3jAAAA: Received packet MESSAGE data 0
INFO:engineio.server:GotWW8oC3BEz4J3jAAAA: Received packet MESSAGE data 0
Client connected
GotWW8oC3BEz4J3jAAAA: Sending packet MESSAGE data 0{"sid":"w_DlD83bH5OBQRbiAAAB"}
INFO:engineio.server:GotWW8oC3BEz4J3jAAAA: Sending packet MESSAGE data 0{"sid":"w_DlD83bH5OBQRbiAAAB"}
127.0.0.1 - - [06/Mar/2025 17:40:50] "POST /socket.io/?EIO=4&transport=polling&t=PLiLCOy&sid=GotWW8oC3BEz4J3jAAAA HTTP/1.1" 200 202 0.003777
Backend sends a continuous message
emitting event "continuous_message" to all [/]
INFO:socketio.server:emitting event "continuous_message" to all [/]
GotWW8oC3BEz4J3jAAAA: Sending packet MESSAGE data 2["continuous_message",{"data":"New continuous message"}]
INFO:engineio.server:GotWW8oC3BEz4J3jAAAA: Sending packet MESSAGE data 2["continuous_message",{"data":"New continuous message"}]
Backend sends a continuous message
emitting event "continuous_message" to all [/]
INFO:socketio.server:emitting event "continuous_message" to all [/]
GotWW8oC3BEz4J3jAAAA: Sending packet MESSAGE data 2["continuous_message",{"data":"New continuous message"}]
INFO:engineio.server:GotWW8oC3BEz4J3jAAAA: Sending packet MESSAGE data 2["continuous_message",{"data":"New continuous message"}]

Client logs

Frontend is requesting a standard message
Firefox can’t establish a connection to the server at ws://localhost:5000/socket.io/?EIO=4&transport=websocket&sid=GotWW8oC3BEz4J3jAAAA.
WebSocket disconnected
Share Improve this question edited Mar 6 at 16:50 tvoirand asked Mar 2 at 11:11 tvoirandtvoirand 4401 gold badge5 silver badges14 bronze badges 7
  • Please add server and client-side logs to your question. When connections fail there is always clues that point to the reason in the logs. – Miguel Grinberg Commented Mar 3 at 11:47
  • Thanks for your comment. I just added the logs to my question. – tvoirand Commented Mar 4 at 7:52
  • I should have been more clear, the logs that are useful are the Socket.IO logs. See flask-socketio.readthedocs.io/en/latest/… for information on how to configure Socket.IO to output logging data. – Miguel Grinberg Commented Mar 4 at 12:42
  • Sorry, I could have guessed that. I updated my question with socketio logs on the server-side (after adding logger=True, engineio_logger=True to SocketIO() and setting level to DEBUG) and on the client-side (after adding localStorage.dbug = '*'; but it doesn't seem to have any effect). I hope that this adds more useful information. – tvoirand Commented Mar 6 at 16:51
  • The server logs show two background messages that were sent. There are no errors in this log. The client log shows a failure to connect over WebSocket, which means that the connection was based on HTTP long polling. I'm not really sure about the WebSocket failure. Maybe you should try this after uninstalling eventlet, which is not a well maintained library anymore. – Miguel Grinberg Commented Mar 6 at 23:36
 |  Show 2 more comments

2 Answers 2

Reset to default 0

The server logs show two background messages that were sent. There are no errors in this log.

The client log shows a failure to connect over WebSocket, which means that the connection was based on HTTP long polling. I'm not really sure about the WebSocket failure, but considering you are using eventlet and this library hasn't been maintained in a long time you should drop it.

Long time ago Flask-SocketIO needed eventlet or gevent to support WebSocket, but with current versions they are not needed anymore. You can have a WebSocket enabled Flask-SocketIO server using the Flask dev server during development and switching to Gunicorn with the threaded worker for production.

Your BASE_URL needs to be changed. See updated app.js implementation which has been tested locally and seems to work correctly:

const myButton = document.getElementById('my-button');
const BASE_URL = "http://0.0.0.0:5000" // or ws://0.0.0.0:5000;

// Continuous messages #########################################
const socket = io(BASE_URL);

socket.on('connect', () => {
    console.log('WebSocket connected');
});

socket.on('disconnect', () => {
    console.log('WebSocket disconnected');
});

socket.on('continuous_message', (data) => {
    console.log('Frontend received a continuous message:', data);
});
// #############################################################

async function receiveStandardMessage() {
    console.log('Frontend is requesting a standard message');
    const response = await fetch(`${BASE_URL}/standard-message`);
    const data = await response.json();
    console.log('Frontend received a standard message:', data);
}

myButton.addEventListener('click', receiveStandardMessage);

发布评论

评论列表(0)

  1. 暂无评论