轮询 长轮询 长连接
1. 轮询 Http (无状态请求连接)
- 每秒钟发起至少100次, 请求收取消息
- 客户端有一定的处理能力
- 服务器有极快的处理速度
缺点: 客户端服务器, 浪费资源严重, 宽带浪费
2. 长轮询 Http
先去连接服务器, 不断开连接, 保持一定时间, 断开瞬间再次发起连接
- 浪费服务器资源严重
- 节省客户端资源
- 相对实时性消息
3. 长连接 基于Http发起握手
保持和服务器的长连接永不断来, 除非有一端主动发起断开请求
- 发是发, 收是收, 互不影响
- 在客户端和服务器上各有一个轮询
- 双端分担压力
- 消息及时性
缺点: 占用连接资源, 占用网络资源
WebSocket
服务器主动给客户端发送消息 (web -> socket)
websocket 客户端与 websocket 服务器, 达成一个websocket协议
群聊 (group_chat)
视图:
from flask import Flask, request
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
from geventwebsocket.websocket import WebSocket
app = Flask(__name__)
user_socket_list = [] # 存放每一个WebSocket(聊天用户)对象
@app.route('/conn_ws')
def websocket_func():
user_socket = request.environ.get('wsgi.websocket') # type:WebSocket # 获取每一个对象
user_socket_list.append(user_socket)
while True:
msg = user_socket.receive()
print(msg)
for u_socket in user_socket_list:
u_socket.send(msg)
if __name__ == '__main__':
http_server = WSGIServer(('0.0.0.0', 9090), app, handler_class=WebSocketHandler)
http_server.serve_forever() # 启动
1. request.environ # 获取发来的请求对象
< geventwebsocket.websocket.WebSocket object at 0x00000135B14A1F50 >
2. handler_class=WebSocketHandler: 请求一进来, 如果不是http请求, 通过WebSocketHandler做处理
3. 在WSGIServer中加入了WebSocket的处理机制
前端状态码:
# readyState: 1 # 已经开启了websocket连接
# readyState: 3 # 开启了websocket, 但又断开连接
# 前端 (html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="text" id="send_msg">
<button id="send_btn" onclick="send()">发送消息</button>
<p><div id="chat_list "></div></p>
</body>
<script type="application/javascript">
var ws = new WebSocket('ws://192.168.11.51:9090/conn_ws');
ws.onmessage = function (messageEvent) {
console.log(messageEvent.data);
var ptag = document.createElement("p");
ptag.innerText = messageEvent.data;
document.getElementById('chat_list').appendChild(ptag);
};
function send() {
var send_msg = document.getElementById('send_msg').value;
ws.send(send_msg);
}
</script>
</html>
单聊 (private chat)
# 视图
import json
from flask import Flask, request, render_template
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
from geventwebsocket.websocket import WebSocket
app = Flask(__name__)
user_socket_dict = {}
@app.route('/conn_ws/<user_nick>')
def websocket_func(user_nick):
user_socket = request.environ.get('wsgi.websocket') # type:WebSocket
user_socket_dict[user_nick] = user_socket
while True:
msg = user_socket.receive()
msg_dict = json.loads(msg)
to_user = msg_dict.get('to_user')
to_user_socket = user_socket_dict.get(to_user)
to_user_socket.send(msg)
@app.route('/')
def index():
return render_template('single_chat.html')
if __name__ == '__main__':
http_server = WSGIServer(('0.0.0.0', 9090), app, handler_class=WebSocketHandler)
http_server.serve_forever() # 启动
# msg = {from_user:"jason",to_user:"jake",message:"666"}
# 模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>
<input type="text" id="nick">
<button onclick="login()">登陆聊天室</button>
</p>
发送给: <input type="text" id="to_user">消息: <input type="text" id="send_msg">
<button id="send_btn" onclick="send()">发送消息</button>
<div id="chat_list"> </div>
</body>
<script type="application/javascript">
var ws = null;
function login() {
var nick = document.getElementById('nick').value;
ws = new WebSocket('ws://192.168.11.51:9090/conn_ws/'+nick);
ws.onmessage = function (messageEvent) {
console.log(messageEvent.data);
var ptag = document.createElement("p");
var message = JSON.parse(messageEvent.data);
ptag.innerText = message.from_user + " : " + message.message;
document.getElementById('chat_list').appendChild(ptag);
};
}
// 发送消息
function send() {
var message = document.getElementById('send_msg').value;
var send_msg = {
from_user: document.getElementById('nick').value,
to_user: document.getElementById('to_user').value,
message:message
};
var json_send_msg = JSON.stringify(send_msg);
ws.send(json_send_msg);
}
</script>
</html>