如何用Ctrl+C结束Flask SocketIO,报错403(禁止访问)
How to end Flask SocketIO with Crtl+C, Error 403 (Forbidden)
如何优雅地结束套接字?我尝试使用 signal.SIGINT
但没有成功。
还有其他方法吗? 我正在 运行 开发中,似乎无法在 Crtl+C 后停止套接字。当 app.py 再次启动时,浏览器控制台日志继续打印并锁定浏览器以防止重新加载页面。
这是我的app.py
from logging.handlers import SocketHandler
import os
import pandas as pd
import json
import threading
import signal
from flask import Flask, render_template, session, request, jsonify
from flask_socketio import SocketIO
from flask_cors import CORS, cross_origin
app = Flask(__name__)
app.debug = True
socketio = SocketIO(
app, cors_allowed_origins="*", always_connect=True, async_mode="threading"
)
app.config["SECRET_KEY"] = "secret!"
def signal_handler(signum, frame):
exit_event.set()
SocketHandler.close(socketio)
exit_event = threading.Event()
@socketio.on("response_demo")
def background_task_func():
"""Example of how to send server generated events to clients."""
i = 0
while True:
if exit_event.is_set():
print(f"completed {threading.current_thread().name} : {os.getpid()} ")
socketio.disconnect()
socketio.settimeout(2)
socketio.close()
# SocketHandler.close(socketio)
break
socketio.sleep(5.05)
data = {
"Name": "data packet",
"p": [{"x": i, "a": 12, "b": 12, "c": 10, "d": 10, "e": 10}],
}
data_2 = pd.DataFrame(data)
df_json = data_2.to_json(orient="records")
result = {"objects": json.loads(df_json)}
socketio.emit("my_response", result, broadcast=True)
@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "GET":
return render_template("index-so.html")
exit_event.clear()
val = request.json.get("c_check")
bg = threading.Thread(target=background_task_func, daemon=True)
if val == 1:
# bg.start()
print(f"c_check = 1")
elif val == 0:
try:
print("trying to kill thread")
exit_event.set()
except Exception as e:
print(e)
print("val0 is ", val)
response = jsonify({"data": {"val": val}})
return response
if __name__ == "__main__":
signal.signal(signal.SIGINT, signal_handler)
socketio.run(
app, logger=True, engineio_logger=True, use_reloader=True, debug=True, port=5000
)
Ctrl-C 停止服务器。您看到的错误来自客户端,它在浏览器中运行并且完全独立。
这些错误的发生是因为 Socket.IO 协议实现了连接重试。这其实是好事,不是坏事。在生产站点上,当服务器离线一段时间时,可能是升级后重新启动的结果,来自客户端的重试确保在服务器恢复接收流量后立即重新建立连接。
如果你想让你的客户端不再尝试重新连接,你可以配置如下:
var socket = io.connect('http://server.com', {
reconnection: false
});
如何优雅地结束套接字?我尝试使用 signal.SIGINT
但没有成功。
还有其他方法吗? 我正在 运行 开发中,似乎无法在 Crtl+C 后停止套接字。当 app.py 再次启动时,浏览器控制台日志继续打印并锁定浏览器以防止重新加载页面。
这是我的app.py
from logging.handlers import SocketHandler
import os
import pandas as pd
import json
import threading
import signal
from flask import Flask, render_template, session, request, jsonify
from flask_socketio import SocketIO
from flask_cors import CORS, cross_origin
app = Flask(__name__)
app.debug = True
socketio = SocketIO(
app, cors_allowed_origins="*", always_connect=True, async_mode="threading"
)
app.config["SECRET_KEY"] = "secret!"
def signal_handler(signum, frame):
exit_event.set()
SocketHandler.close(socketio)
exit_event = threading.Event()
@socketio.on("response_demo")
def background_task_func():
"""Example of how to send server generated events to clients."""
i = 0
while True:
if exit_event.is_set():
print(f"completed {threading.current_thread().name} : {os.getpid()} ")
socketio.disconnect()
socketio.settimeout(2)
socketio.close()
# SocketHandler.close(socketio)
break
socketio.sleep(5.05)
data = {
"Name": "data packet",
"p": [{"x": i, "a": 12, "b": 12, "c": 10, "d": 10, "e": 10}],
}
data_2 = pd.DataFrame(data)
df_json = data_2.to_json(orient="records")
result = {"objects": json.loads(df_json)}
socketio.emit("my_response", result, broadcast=True)
@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "GET":
return render_template("index-so.html")
exit_event.clear()
val = request.json.get("c_check")
bg = threading.Thread(target=background_task_func, daemon=True)
if val == 1:
# bg.start()
print(f"c_check = 1")
elif val == 0:
try:
print("trying to kill thread")
exit_event.set()
except Exception as e:
print(e)
print("val0 is ", val)
response = jsonify({"data": {"val": val}})
return response
if __name__ == "__main__":
signal.signal(signal.SIGINT, signal_handler)
socketio.run(
app, logger=True, engineio_logger=True, use_reloader=True, debug=True, port=5000
)
Ctrl-C 停止服务器。您看到的错误来自客户端,它在浏览器中运行并且完全独立。
这些错误的发生是因为 Socket.IO 协议实现了连接重试。这其实是好事,不是坏事。在生产站点上,当服务器离线一段时间时,可能是升级后重新启动的结果,来自客户端的重试确保在服务器恢复接收流量后立即重新建立连接。
如果你想让你的客户端不再尝试重新连接,你可以配置如下:
var socket = io.connect('http://server.com', {
reconnection: false
});