Flask - WebSocket
WebSocket介绍
概念:
是一套协议,协议规定了:
- 连接时需要握手
- 发送数据进行加密
- 连接之后不断开
意义:
实现长轮询等操作
框架支持
-
flask,gevent-websocket
-
django,channel
-
torando框架自带
应用场景:
实时响应页面时,可以使用websocket。
缺点:
兼容性比较差,版本较低的IE无法支持
使用方法:
pip install gevent
pip install websocket
导入
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()
注意: 端口要一致,不要运行Flask项目, 正常情况下启动后,处于监听状态.
后端操作
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("你好呀") // 向服务端发送消息
基于WebSocket的群聊实例
py文件
from flask import Flask ,request,render_template
from geventwebsocket.websocket import WebSocket,WebSocketError
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
import json
app = Flask(__name__)
@app.route('/index/')
def index():
return render_template('websocket.html')
# user_socket_list = []
user_socket_dict={}
@app.route('/ws/<username>')
def ws(username):
user_socket=request.environ.get("wsgi.websocket")
if not user_socket:
return "请以WEBSOCKET方式连接"
user_socket_dict[username]=user_socket
print(user_socket_dict)
while True:
try:
user_msg = user_socket.receive()
for user_name,u_socket in user_socket_dict.items():
who_send_msg={
"send_user":username,
"send_msg":user_msg
}
if user_socket == u_socket:
continue
u_socket.send(json.dumps(who_send_msg))
except WebSocketError as e:
user_socket_dict.pop(username)
print(user_socket_dict)
print(e)
if __name__ == '__main__':
http_serve=WSGIServer(("0.0.0.0",5000),app,handler_class=WebSocketHandler)
http_serve.serve_forever()
html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-4">
<h2 style="text-align: center">激情群聊</h2>
<div class="form-group">
<label for="username">你是谁:</label>
<input class="form-control" type="text" id="username">
</div>
<button id="create_ws" onclick="go_to()" class="btn btn-warning">创建ws连接</button>
<div style=" 100%; height: 300px; border: thick;background-color: cadetblue" id="chat_window" class="input-group">
</div>
<div class="input-group">
<input type="text" class="form-control" placeholder="" id="send_msg">
<span class="input-group-btn">
<button class="btn btn-default" type="button" id="btn_send">发送消息</button>
</span>
</div>
</div>
</div>
</div>
</div>
<script type="application/javascript">
var ws_url="ws://192.168.12.70:5000/ws/";
var ws =null;
function go_to() {
var username = document.getElementById('username');
ws = new WebSocket(ws_url+username.value);
ws.onmessage=function(serv_msg){
msg=JSON.parse(serv_msg.data);
//console.log(serv_msg.data);
create_chart('y',msg)
};
}
function create_chart(self,content) {
if (self == "w"){
self = "right";
var spantag = document.createElement("span");
spantag.innerText= content.send_msg;
var spantag1 = document.createElement("span");
spantag1.innerText=':我';
}else{
self = "left";
var spantag = document.createElement("span");
spantag.innerText=content.send_user+':';
var spantag1 = document.createElement("span");
spantag1.innerText=content.send_msg;
}
var divtag = document.createElement("div");
divtag.style="text-align:"+self;
divtag.appendChild(spantag);
divtag.appendChild(spantag1);
var char_window = document.getElementById('chat_window');
char_window.appendChild(divtag);
}
document.getElementById("btn_send").addEventListener("click",function () {
var send_msg=document.getElementById("send_msg");
ws.send(send_msg.value);
var s_msg = {send_msg:send_msg.value};
create_chart('w',s_msg);
send_msg.value='';
})
</script>
</body>
</html>
基于WebSocket的单聊实例
py文件
from flask import Flask ,request,render_template
from geventwebsocket.websocket import WebSocket,WebSocketError
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
import json
app = Flask(__name__)
@app.route('/index/')
def index():
return render_template('one2one.html')
user_socket_list = []
user_socket_dict={}
@app.route('/ws/<username>')
def ws(username):
user_socket=request.environ.get("wsgi.websocket")
if not user_socket:
return "请以WEBSOCKET方式连接"
user_socket_dict[username]=user_socket
print(user_socket_dict)
while True:
try:
user_msg = user_socket.receive()
user_msg=json.loads(user_msg)
to_user_socket = user_socket_dict.get(user_msg.get("to_user"))
send_msg={
"send_msg":user_msg.get("send_msg"),
"send_user":username
}
to_user_socket.send(json.dumps(send_msg))
except WebSocketError as e:
user_socket_dict.pop(username)
print(user_socket_dict)
print(e)
if __name__ == '__main__':
http_serve=WSGIServer(("0.0.0.0",5000),app,handler_class=WebSocketHandler)
http_serve.serve_forever()
html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-4">
<h2 style="text-align: center">激情聊天</h2>
<div class="form-group">
<label for="username">你是谁:</label>
<input class="form-control" type="text" id="username">
</div>
<div class="form-group">
<label for="to_user">发送谁:</label>
<input class="form-control" type="text" id="to_user">
</div>
<button id="create_ws" onclick="go_to()" class="btn btn-warning">创建ws连接</button>
<div style=" 100%; height: 300px; border: double;background-color: cadetblue" id="chat_window" class="input-group">
</div>
<div class="input-group">
<input type="text" class="form-control" placeholder="" id="send_msg">
<span class="input-group-btn">
<button class="btn btn-default" type="button" id="btn_send">发送消息</button>
</span>
</div>
</div>
</div>
</div>
</div>
<script type="application/javascript">
var ws_url = "ws://192.168.12.70:5000/ws/";
var ws = null;
function go_to() {
var username = document.getElementById('username');
ws = new WebSocket(ws_url + username.value);
ws.onmessage = function (serv_msg) {
msg = JSON.parse(serv_msg.data);
//console.log(serv_msg.data);
create_chart('y', msg)
};
}
function create_chart(self, content) {
if (self == "w") {
self = "right";
var spantag = document.createElement("span");
spantag.innerText = content.send_msg;
var spantag1 = document.createElement("span");
spantag1.innerText = ':我';
} else {
self = "left";
var spantag = document.createElement("span");
spantag.innerText = content.send_user + ':';
var spantag1 = document.createElement("span");
spantag1.innerText = content.send_msg;
}
var divtag = document.createElement("div");
divtag.style = "text-align:" + self;
divtag.appendChild(spantag);
divtag.appendChild(spantag1);
var char_window = document.getElementById('chat_window');
char_window.appendChild(divtag);
}
document.getElementById("btn_send").addEventListener("click", function () {
var send_msg = document.getElementById("send_msg");
var to_user = document.getElementById("to_user");
send_msg_json = {
send_msg: send_msg.value,
to_user: to_user.value
};
ws.send(JSON.stringify(send_msg_json));
var s_msg = {send_msg: send_msg.value};
create_chart('w', s_msg);
send_msg.value = '';
})
</script>
</body>
</html>