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

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

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

首先安装下列依赖:

1
2
3
4
5
6
7
8
9
10
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代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 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文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!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代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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来实现了,

关于流响应可以参考文档