14-2 聊天室实现思路:轮训、长轮训、websocket_哔哩哔哩_bilibili 参考大佬的B站学习笔记
https://www.cnblogs.com/wupeiqi/p/6558766.html 参考博客
https://www.cnblogs.com/wupeiqi/articles/9593858.html 参考博客
http: 是短连接,无状态的,一次性的,无法保证实时信息交互
- 客户端主动连接服务器
- 客户端向服务端发送消息,服务端接收到返回数据
- 客户端接收到数据
- 端口连接
websock协议创建持久的连接不断开,基于这个连接进行收发数据,建立在http上
- 实时响应:接收发送消息
- 实时图表,柱状图,饼图
websocket 原理:
- 连接,客户端发起
- 握手,客户端发送一个消息,后端接收到消息再做一些特殊处理返回(服务端要支持websocket协议)
- 收发数据(加密)
- 断开连接
握手流程:
1.客户端向服务端发送
GET /chatsocket HTTP/1.1
Host: 127.0.0.1:8002
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: http://localhost:63342
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: mnwFxiOlctXFN/DeMt1Amg==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
2.服务端接收:
请求和响应的【握手】信息需要遵循规则:从请求【握手】信息中提取 Sec-WebSocket-Key利用magic_string 和 Sec-WebSocket-Key 进行hmac1加密,再进行base64加密将加密结果响应给客户端注:magic string固定为:258EAFA5-E914-47DA-95CA-C5AB0DC85B11
返回数据给客户端浏览器,验证通过则完成握手
HTTP/1.1 101 Switching Protocols"Upgrade:websocket"Connection: Upgrade"Sec-WebSocket-Accept: 密文
收发数据流程:
数据 b'asdfa;efawe;sdfas;awdfawea;sdfasdfaf;sdfasdfa;'
先获取第二个字节,8位 10001010
再获取第二个字节的后七位 0001010 -> payload len
- =127 2个字节,8个字节 其他字节(4字节 masking key + 数据)
- =126 2个字节,8个字节 其他字节(4字节 masking key + 数据)
- <=125 2个字节 其他字节(4字节 masking key + 数据)
- 获取masking key,然后对数据进行解密
var DECODED = "";
for (var i = 0; i < ENCODED.length; i++) {
DECODED[i] = ENCODED[i] ^ MASK[i % 4];
}
实时交互的解决方案:
- 轮训,浏览器每隔一段时间向后台发送一次请求。缺点:有延迟、请求太多网站压力大
- 长轮询,客户端向服务端发送请求,保持一定的时间,一旦有数据就立即返回。特点:数据无延迟,常应用于大平台、WebQQ、Web微信
- websocket,客户端和服务端创建连接不断开,可以实现双向通信。特点:旧版浏览器不支持
django 中配置websocket
pip install channels # 安装组件# 注册app
'channels' # 配置asgi.application
ASGI_APPLICATION = 'web.asgi.application'
更新asgi文件(在支持http的基础上支持websocket)
# asgi.pyimport os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter,URLRouter
from . import routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'web.settings')application = ProtocolTypeRouter({'http':get_asgi_application(),'websocket':URLRouter(routing.websocket_urlpatterns),
})
创建routing文件在setting同级目录
from django.urls import re_pathfrom app import consumerswebsocket_urlpatterns = [re_path(r'ws/(?P<group>\w+)/$',consumers.ChatConsumer.as_asgi()),
]
创建app目录下consumer文件
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer"""
wsgi: 同步
asgi: 异步+asgi+websocket
"""
class ChatConsumer(WebsocketConsumer):def websocket_connect(self, message):# 客户端向后端发送websocket连接请求时自动触发# 容许和客户端创建连接self.accept()def websocket_receive(self, message):# 浏览器基于websocket向后端发送数据,自动触发接收消息print(message)self.send('不要回复!!!')def websocket_disconnect(self, message):# 客户端与服务端断开时自动触发raise StopConsumer
2024/02/26 更新中。。。