首页 > 解决方案 > 从线程发射时,Flask Socket.io 不起作用

问题描述

描述

客户端有2个按钮:

这个问题是我试图解决的真正问题的代表。

我构建了应用程序,在服务器端它似乎工作,但客户端没有收到服务器推送,但能够启动推送并杀死它!

我试过的

服务器端

import random
from threading import Thread
from time import sleep

from flask import Flask
from flask_socketio import SocketIO

SOCKET_NAMESPACE = '/test'

is_pushing = False

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!!'
socketio = SocketIO(app)


def server_push(fps):
    dt = 1 / fps
    global is_pushing
    while is_pushing:
        with app.test_request_context('/'):
            sent = f"Server Pushed!! {random.random()}"
            print(sent)
            socketio.emit("serverResponse", sent, namespace=SOCKET_NAMESPACE)
            sleep(dt)


@socketio.on('connect', namespace=SOCKET_NAMESPACE)
def on_connect():
    print("connected server!!")
    socketio.emit("serverResponse", "First Push", namespace=SOCKET_NAMESPACE)


@socketio.on('disconnect', namespace=SOCKET_NAMESPACE)
def on_disconnect():
    print("disconnected server!!")


@socketio.on('startServerPush', namespace=SOCKET_NAMESPACE)
def on_start_server_push(fps=1):
    print("Sever push start!!")
    global is_pushing
    is_pushing = True
    socketio.emit("serverResponse", "Start Push", namespace=SOCKET_NAMESPACE)
    Thread(target=lambda: server_push(fps)).start()


@socketio.on("killServerPush", namespace=SOCKET_NAMESPACE)
def on_kill_server_push():
    print("Server push stop!!")
    global is_pushing
    is_pushing = False
    socketio.emit("serverResponse", "Kill Push", namespace=SOCKET_NAMESPACE)


def main():
    socketio.run(app, port=8082, debug=True)


if __name__ == '__main__':
    main()

客户端

import openSocket from 'socket.io-client';
import React, { Component } from 'react';

class Test extends Component {
  state = {
    pushedFromServer: [],
    socket: null
  };

  componentDidMount() {
    const url = 'localhost:8082/test';
    const socket = openSocket(url);
    socket.on('connect', () => console.log('Test connected!!'));
    socket.on('disconnect', () => console.log('Test disconnected!!'));
    socket.on('serverResponse', response => {
      console.log(response);
      const pushedFromServer = [...this.state.pushedFromServer];
      pushedFromServer.push(response);
      this.setState({ pushedFromServer });
    });
    this.setState({ socket });
  }

  killServerPush = () => {
    this.state.socket.emit('killServerPush');
  };

  startServerPush = () => {
    this.state.socket.emit('startServerPush');
  };

  render() {
    return (
      <div>
        <button onClick={this.startServerPush}>
          <h3>Start push from server</h3>
        </button>
        <button onClick={this.killServerPush}>
          <h3>Kill push from server</h3>
        </button>
        <ul>
          {this.state.pushedFromServer.map(value => (
            <li>{value}</li>
          ))}
        </ul>
      </div>
    );
  }
}

export default Test;

最后的笔记

在客户端,我可以收到First PushStart Push,我还可以从客户端停止周期性进程并重新启动它。我无法在客户端接收定期消息

谢谢

标签: pythonmultithreadingflasksocket.io

解决方案


通过查看https://github.com/miguelgrinberg/python-socketio/issues/99,我找到了该问题的解决方案。

只需要更改服务器端。

换线:

Thread(target=lambda: server_push(fps)).start()

 socketio.start_background_task(target=lambda: server_push(fps))

而不是使用 python sleep,而是使用:

socketio.sleep(dt)

推荐阅读