python,from flask import Flask, Response,import timeapp = Flask(__name__)@app.route('/stream'),def stream():, def generate():, count = 0, while True:, yield f"data: {count}", count += 1, time.sleep(1), return Response(generate(), content_type='text/event-stream')if __name__ == '__main__':, app.run(),
` 这段代码创建了一个简单的Flask应用,其中定义了一个
/stream 路由,该路由会生成一个无限循环的事件流,每秒发送一次数据。客户端可以通过打开
/stream` URL来接收这些事件。
服务器发送事件(SSE)服务器端代码详解
一、
服务器发送事件(Server-Sent Events,简称 SSE)是一种服务器向客户端推送数据的机制,通过在服务器端设置合适的响应头和按照特定格式发送数据,客户端可以持续接收来自服务器的实时更新,无需频繁轮询服务器,有效提高了数据传输的效率和实时性,下面将详细介绍使用 Python 的 Flask 框架实现 SSE 服务器端代码的过程。
二、环境搭建
在开始编写代码之前,需要确保已经安装了 Flask 库,如果尚未安装,可以使用以下命令进行安装:
pip install flask
三、代码实现
导入 Flask 模块,以便创建 Flask 应用实例。
from flask import Flask, Response
创建一个 Flask 应用对象,用于处理请求和响应。
app = Flask(__name__)
1、设置响应头
Content-Type
:设置为text/event-stream
,表示响应内容为服务器发送事件流。
Cache-Control
:设置为no-cache
,防止浏览器缓存响应内容,确保每次接收到的都是最新的数据。
Connection
:设置为keep-alive
,保持连接处于活动状态,以便服务器可以持续向客户端发送数据。
2、生成并发送事件数据
使用一个无限循环来模拟实时数据的生成和发送,在实际应用中,可以根据具体需求替换为从数据库读取数据、监听外部事件等操作。
每个事件数据由data
字段携带,可以根据需要添加其他自定义字段,如event
字段用于指定事件类型。
使用flush()
方法将数据立即发送给客户端,而不是等待缓冲区满。
以下是完整的 SSE 路由及处理函数代码示例:
@app.route('/sse') def sse(): def generate(): i = 0 while True: # 模拟生成实时数据,这里简单地使用递增的数字作为数据 data = f'Event: message Data: {i} ' yield data.encode('utf-8') i += 1 # 每隔 1 秒发送一次数据,可根据实际需求调整时间间隔 time.sleep(1) headers = { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' } return Response(generate(), headers=headers)
在代码的最后,调用app.run()
方法启动 Flask 应用,并指定主机地址和端口号,本地开发时可以使用默认的127.0.0.1
地址和任意可用端口,5000。
if __name__ == '__main__': app.run(host='127.0.0.1', port=5000)
四、相关问题与解答
(一)问题:如何让多个客户端同时接收 SSE 推送的数据?
解答:Flask 本身是多线程或多进程的(取决于运行模式),可以同时处理多个客户端的请求,当多个客户端连接到/sse
路由时,服务器会为每个客户端分别执行generate()
函数,并为其生成独立的事件流,每个客户端都可以独立地接收来自服务器的实时数据推送,互不干扰。
(二)问题:如果在发送 SSE 数据过程中发生异常,如何处理?
解答:可以在generate()
函数中使用try...except
语句块来捕获可能发生的异常,当捕获到异常时,可以选择记录错误日志,然后根据具体情况决定是否继续发送数据或者关闭连接。
def generate(): i = 0 while True: try: data = f'Event: message Data: {i} ' yield data.encode('utf-8') i += 1 time.sleep(1) except Exception as e: print(f"An error occurred: {e}") # 根据需求选择是否继续发送数据或者关闭连接 # 可以在这里使用 break 语句退出循环,结束事件流 break
这样可以避免因单个客户端的异常导致整个服务器端出现问题,同时也能及时记录和处理异常情况,保证系统的稳定性和可靠性。