Flask+HTML5实现服务器推送事件

服务器推送事件(server-sent events,SSE)是一种除websocket、ajax简单轮寻外另一种实现服务器数据主动推送数据到浏览器的方式。

这里,举一个的例子来说明如何使用基于pyhon的服务端来实现,为了简单我使用flask框架来实现。关键点有2个:

  1. HTTP响应头中包含content-type:text/event-stream
  2. 流响应

首先安装下列依赖:

click==6.6
eventlet==0.19.0
Flask==0.11.1
Flask-Cors==2.1.2
greenlet==0.4.10
itsdangerous==0.24
Jinja2==2.8
MarkupSafe==0.23
six==1.10.0
Werkzeug==0.11.10

安装完成后app.py代码如下:

# coding=utf-8
'''
@Author:Roy.S
@CreateDate: 2016年 08月 04日 星期四 10:56:37 HKT
@Description:配合html5测试服务端推送事件
'''

import random
import eventlet
eventlet.monkey_patch()
from flask_cors import CORS, cross_origin
from flask import Flask, Response
app = Flask(__name__)
CORS(app)  #注意这里的CORS


def event():
    while True:
        yield 'data:%s \n\n' % random.random()
        eventlet.sleep(1)


@app.route('/stream/', methods=['GET', 'POST'])
def stream():
    return Response(event(), mimetype="text/event-stream") # 注意这里的响应类型

if __name__ == '__main__':
    app.run()

这里有个小地方需要注意就是CORS的问题,不添加这个的话会报错'Access-Control-Allow-Origin' header is present on the requested resource.

为了简单这里就不进行更精细的跨域控制了。

接下来编写HTML文件:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>测试服务端主动推送</title>
    <script src="webevent.js" charset="utf-8"></script>
</head>

<body>
    <h1>data</h1>
    <div id='serverData'>

    </div>
    <h1>status</h1>
    <div id='serverStatus'>

    </div>
</body>

</html>

两个DIV分别用来显示接收到的数据和服务端状态。webevent.js代码如下:

var serverData;
var serverStatus;
var url = 'http://127.0.0.1:5000/stream/' //服务端地址

window.onload = function() {
    serverData = document.getElementById('serverData');
    serverStatus = document.getElementById('serverStatus');
    startListenServer()
}

function startListenServer() {
    serverStatus.innerHTML = "start connect server";
    var es = new EventSource(url); //连接服务器
    es.onopen = open;
    es.onerror = error;
    es.onmessage = msg;
}

function open(e) {
    serverStatus.innerHTML = "server open";
}

function error(e) {
    serverStatus.innerHTML = "server error";
}

function msg(e) {
    serverData.innerHTML = e.data;  // e.data即服务器返回的数据
}

这里重点就是onopen、onerror、onmessage这3个事件了,分别对应开始链接、链接错误、接收到数据的处理。

完成后,使用python app.py启用服务器后,在浏览器中访问编写的HTML文件,就可以看到结果了。


另外,flask已经有现成的插件flask-sse来实现了,

关于流响应可以参考文档