websocket
概念
是一套协议,协议规定了:
- 连接时需要握手
- 发送数据进行加密
- 连接之后不断开
意义
实现长轮询等操作
框架支持
– flask,gevent-websocket
– django,channel
– torando框架自带
应用场景
实时响应页面时,可以使用websocket。
缺点
兼容性比较差,版本较低的IE无法支持
使用方法
导入
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
启动
Flask 的启动的地方改成这样即可以支持 websocket ,同时并不会覆盖 http ,两者并存
if __name__ == '__main__':
http_server = WSGIServer(('0.0.0.0', 5000), app, handler_class=WebSocketHandler)
http_server.serve_forever()
后端操作
ws = request.environ.get('wsgi.websocket') # 要拿到websocket 的标识才可以操作msg = ws.receive() # 从客户端接收消息ws.send("你好啊") # 向客户端发送消息
前端操作
var ws = new WebSocket('ws://127.0.0.1:5000/message') // 不定义的话默认就是 HTTP,定义后往指定的url 发起 websocket 链接请求ws.onmessage = function (event) { // 服务器端向客户端发送数据时,自动执行
var response = JSON.parse(event.data); // 接收服务端的数据
};ws.send("你好呀") // 向服务端发送消息
示例
前端
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>丑男投票系统</h1>
<ul>
{% for k,v in users.items() %}
<li onclick="vote({{k}})" id="id_{{k}}">{{v.name}}<span>{{v.count}}</span></li>
{% endfor %}
</ul> <script src="{{ url_for('static',filename='jquery-3.3.1.min.js')}}"></script>
<script>
var ws = new WebSocket('ws://127.0.0.1:5000/message')
ws.onmessage = function (event) {
/* 服务器端向客户端发送数据时,自动执行 */
// {'cid':cid,'count':new}
var response = JSON.parse(event.data);
$('#id_'+response.cid).find('span').text(response.count); }; function vote(cid) {
ws.send(cid) // 发送信息
}
</script>
</body>
</html>
后端
from flask import Flask,render_template,request
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
import jsonapp = Flask(__name__)USERS = {
'':{'name':'钢弹','count':0},
'':{'name':'铁锤','count':0},
'':{'name':'贝贝','count':100},
}# http://127.0.0.1:5000/index
@app.route('/index')
def index():
return render_template('index.html',users=USERS)# http://127.0.0.1:5000/message
WEBSOCKET_LIST = []
@app.route('/message')
def message():
ws = request.environ.get('wsgi.websocket')
if not ws:
print('http')
return '您使用的是Http协议'
WEBSOCKET_LIST.append(ws)
while True:
cid = ws.receive() # 接收信息
if not cid:
WEBSOCKET_LIST.remove(ws)
ws.close()
break
old = USERS[cid]['count']
new = old + 1
USERS[cid]['count'] = new
for client in WEBSOCKET_LIST:
client.send(json.dumps({'cid':cid,'count':new}))if __name__ == '__main__':
http_server = WSGIServer(('0.0.0.0', 5000), app, handler_class=WebSocketHandler)
http_server.serve_forever()