You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python端检测到Socket.io连接,但JavaScript客户端无事件触发

Flask-SocketIO连接成功但前端无响应的问题修复

核心问题分析

你的代码存在两个关键问题导致前端无法收到事件:

  1. 事件线程阻塞:在handle_connect中直接调用start_sending,而该函数是无限循环逻辑,会占用整个SocketIO事件线程,导致后续消息推送、事件处理完全卡住。
  2. 双重循环冗余:get_screen本身已包含while True的生成器逻辑,start_sending又嵌套循环遍历生成器,造成逻辑混乱且推送效率低下。

解决方案

1. 用后台任务启动推送逻辑

Flask-SocketIO要求事件处理函数不能长时间阻塞,必须通过socketio.start_background_task将循环/耗时任务放到后台线程执行,避免占用主事件循环。

2. 简化屏幕捕获逻辑

移除get_screen中的无限循环,让它单次调用返回单帧数据,在start_sending中控制推送频率,逻辑更清晰。

3. 确保前后端版本兼容

前端使用SocketIO JS 4.6.0,需对应后端安装Flask-SocketIO 5.x及以上版本,执行命令更新:

pip install flask-socketio>=5.0.0

4. 优化前端连接代码

页面从服务器渲染时,无需手动指定URL,直接用io()即可自动连接当前服务器,提升代码灵活性。

修改后的完整代码

server.py

from flask import Flask, render_template
from flask_socketio import SocketIO, emit
from flask_cors import CORS
import pyautogui
import cv2
import numpy as np
import base64

app = Flask(__name__)
CORS(app)
socketio = SocketIO(app, cors_allowed_origins="*")

# 初始化全局变量
stop_stream = False

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

def get_screen():
    # 单次捕获屏幕并返回编码后的字符串
    screenshot = pyautogui.screenshot()
    frame = np.array(screenshot)
    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
    _, jpeg = cv2.imencode('.jpg', frame)
    encoded_img = base64.b64encode(jpeg.tobytes())
    return encoded_img.decode('utf-8')

@socketio.on('connect')
def handle_connect():
    print('Client connected')
    # 用后台任务启动推送,避免阻塞事件循环
    socketio.start_background_task(start_sending)

def start_sending(): 
    global stop_stream
    stop_stream = False
    while not stop_stream:
        frame = get_screen()
        emit('image', frame)
        socketio.sleep(0.1)  # 控制推送频率,避免过高占用资源

@socketio.on('disconnect')
def handle_disconnect():
    global stop_stream
    stop_stream = True
    print('Client disconnected')

@socketio.on_error_default 
def default_error_handler(e):
    print('An error occurred:', e)

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

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Stream Viewer</title>  
    <script src="https://cdn.socket.io/4.6.0/socket.io.min.js" integrity="sha384-c79GN5VsunZvi+Q/WObgk2in0CbZsHnjEqvFxC5DxHn9lTfNce2WW6h2pH6u/kF+" crossorigin="anonymous"></script>
</head>
<body>
    <img id="screenFrame" style="max-width: 100%;">

    <script> 
        // 自动连接当前服务器,无需手动指定URL
        var socket = io();

        socket.on('connect', function(){
            console.log('连接成功!');
        }); 
        socket.on('disconnect', function(){
            console.log('连接断开!');
        });
        socket.on('error', function(err){
            console.log('Socket错误:', err);
        });

        socket.on('image', data => {
            console.log("收到图像数据");
            const img = document.getElementById('screenFrame');
            img.src = 'data:image/jpeg;base64,' + data;
        });
    </script>
</body>
</html>

验证步骤

  1. 确保安装符合版本要求的Flask-SocketIO:pip install flask-socketio>=5.0.0
  2. 启动服务器:python server.py
  3. 访问http://localhost:5000,打开浏览器控制台查看日志
  4. 此时应能看到“连接成功!”日志,页面同时显示屏幕流

内容的提问来源于stack exchange,提问作者MaikeruDev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 22:58:10