1. websocket
1.1 websocket是什么
- WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议
- WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
- 在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
- Websocket的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
我们可以看一下http和websocket的连接过程
1.2 websocket技术发展
- AJAX轮询
- Long Polling长轮询
我们都知道,不使用WebSocket与服务器实时交互,一般有两种方法。AJAX轮询和Long Polling长轮询。
AJAX轮询
AJAX轮询也就是定时发送请求 (每隔n秒发送request给服务器,询问现在有没有数据更新),也就是普通的客户端与服务端通信过程,只不过是无限循环发送,这样,可以保证服务端一旦有最新消息,就可以被客户端获取。
Long Polling长轮询
Long Polling长轮询是客户端和浏览器保持一个长连接,等服务端有消息返回,断开。
然后再重新连接,也是个循环的过程,无穷尽也。。。
客户端发起一个Long Polling,服务端如果没有数据要返回的话,
会hold住请求,等到有数据,就会返回给客户端。客户端又会再次发起一次Long Polling,再重复一次上面的过程。
- 这个有点像我一直盯着服务器,只要服务器有空,我就要和你建立长连接
缺点
上边这两种方式都有个致命的弱点,开销太大,被动性。假设并发很高的话,这对服务端是个考验。
而WebSocket一次握手,持久连接,以及主动推送的特点可以解决上边的问题,又不至于损耗性能。
1.3 websocket优点
HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
2. Flask-SocketIO
Flask-SocketIO
是python的一个库,通过这个库可以使用python进行websocket通信
首先需要知道,Flask的websocket通信也是需要WSGI的,在使用flask进行websocket的时候,需要认识到这三种WSGI
Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)
- eventlet
- gevent
- Werkzeug
2.1 eventlet
eventlet是性能最好的选项,并支持长轮询和WebSocket传输。
2.2 gevent
许多不同的配置都支持gevent。gevent软件包完全支持长轮询传输,但是与eventlet不同,gevent不具有本机WebSocket支持。要增加对WebSocket的支持,目前有两个选择。安装gevent-websocket 软件包可以为gevent添加WebSocket支持,或者可以使用带有WebSocket功能的uWSGI Web服务器。gevent的使用也是一种性能选择,但比eventlet略低。
2.3 Werkzeug
也可以使用基于Werkzeug的Flask开发服务器,但要注意的是,它缺乏其他两个选项的性能,因此只能用于简化开发工作流程。此选项仅支持长轮询传输。
很显然,要使用websocket通信应该选择eventlet作为WSGI服务器
3.安装 eventlet
pip install eventlet
安装完之后再安装flask-socketio
pip install flask-socketio
安装flask-socketio
后,我们需要知道flask-socketio
的版本号,因为使用websocket
的过程中,肯定是有服务器端和客户端
两端都要运行websocket,一般前端都是使用javascript进行websocket通信的,并且由于flask-socketio是基于websocket深度封装的,所以在前端需要导入一个js文件,前后端的包版本号一定那个要严格按表中的匹配,否则通信失败
4. websocket通信基础
flask使用ws需要进一步封装
我们首先要对一般的flask框架进行再封装
过程
首先导入SocketIO
from flask_socketio import SocketIO
导入后,再对app进行初始化
socketio = SocketIO(app,cors_allowed_origins='*')
# cors_allowed_origins='*' 允许跨源请求
然后将app.run替换成socketio.run
if __name__ == '__main__':
#app.run()
socketio.run(app,host='0.0.0.0',port=5000,debug=True)
# socketio进一步封装
这样基本就完成websocket的封装了
ws的基本知识
使用websocket一般称之为会话,也就是首先客户端打开浏览器通过js脚本会话主动连接到服务器
5. websocket通信实例
客户端
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script type="text/javascript" src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.5/socket.io.js"></script>
</head>
<body>
<div id="t">
</div>
<script type="text/javascript">
$(document).ready(function () {
var url = location.href;
var socket = io.connect(url);
socket.on('test',function (res){
{#alert(res);#}
var t = res;
if (t){
$('#t').append(t).append('<br>');
}
})
})
</script>
</body>
</html>
服务器
from flask import render_template
from flask_socketio import SocketIO,emit
app = Flask(__name__)
app.secret_key = '905008' #session 密钥
# app.debug = True
socketio = SocketIO(app,cors_allowed_origins='*')
@socketio.on('test')
def test123():
print('hello world')
@app.route("/test")
@app.route("/test",methods=["POST","GET"])
def test():
return render_template("user/test.html")
@app.route('/push')
def push():
event_name = 'test'
broadcast_data = "hello world!"
emit(event_name,broadcast_data,broadcast=True,namespace=name_space)
return "done!"
if __name__ == '__main__':
# app.run()
socketio.run(app,host='0.0.0.0',port=5000,debug=True)