如果有需求要实现服务端向客户端主动推送消息时(比如聊天室,群聊室)有哪几种方案
WebSocket 是一种在 Web 应用程序中实现双向通信的协议。相较于传统的 HTTP 请求-响应模式,WebSocket 提供了全双工的通信方式,使得服务器和客户端之间能够实时地进行双向数据传输。
下面是一些 WebSocket 的应用场景:
下载链接:https://pan.baidu.com/s/1wLhkcRV-3awFz9XMxfWegQ?pwd=yyds
提取码:yyds
websocket 就是web版的socket
原来的Web中:
http协议,无状态,短链接
https协议,是http+对数据进行加密
我们在开发过程中想要保留一些状态信息,基于Cookie来做
现在web支持:
http协议
websocket协议,是建立在http协议之上
连接,客户端发起
握手(验证),客户端发送一个消息,服务端收到消息做一些特殊处理并返回。服务器端支持websocket协议。
客户端向服务端发送
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
...
...
服务器接收(重要)*
Sec-WebSocket-Key:mnwFxiOlctXFN/DeMt1Amg==与 magic string 进行拼接
magic string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
v1 = "mnwFxiOlctXFN/DeMt1Amg==" + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
v2 = hmacl(v1)加密1
v3 = base64(v2)加密2
如果服务端匹配成功返回客户端
HTTP/1.1 101 Switching protocols
Upgrade:websocket
Connection:Upgrade
Sec-WebSocket-Accept:密文(v3)
收到数据(加密)
dfanfsdfmkdsgg;fnfsnfonaoiasdono;fsofnoskfaj
先获取两个字节8位。例如10001010
再获取第二个字节的后7位。例如0001010 ——》payload lens
获取masking Key 然后对数据进行解密
var DECODED = " ";
for(var i = 0;i < DECODED.length;i++){
DECODED[i]= ENCODED[i]^ MASK[i%4];
}
断开连接
安装websocket 第三方包
Django默认不支持websocket,需要安装组件
pip3 install channels
配置
注册channels
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels'
]
在setting.py中添加asgi_application
ASGI_APPLICATION = "websocket.asgi.application"
在asgi.py文件中修改
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter,URLRouter
from . import routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'websocketp.settings')
# application = get_asgi_application()
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": URLRouter(routing.websocket_urlpatterns),
})
在setting同级目录下创建websocket_urls.py
from django.urls import re_path
from app01 import websocket_views
websocket_urlpatterns = [
re_path()
]
在app01目录下创建websocket_views.py,编写处理websocket的业务逻辑
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
class ChatConsumer(WebsocketConsumer):
def websocket_connect(self, message):
# 有客户端来向服务端发送websocket连接的请求时,自动触发
# 服务端允许和客户端创建连接
self.accept()
def websocket_receive(self, message):
# 浏览器基于websocket向服务端发送数据,自动触发接收客户端消息
print(message)
self.send("你好呀你好")
self.close() #表示服务器端主动断开连接
def websocket_disconnect(self, message):
# 客户端与服务器断开连接时,自动触发
print("断开连接")
raise StopConsumer()
在Django中:
访问地址看到聊天室的页面,http请求
让客户端主动向服务端发起websocket连接,服务端接收连接后通过(握手)。
客户端,websocket。
socket = new WebSocket("ws://localhost:8000/room/123/");
服务端 握手并连接成功
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
class ChatConsumer(WebsocketConsumer):
def websocket_connect(self, message):
print("有人来连接了....")
# 有客户端来向服务端发送websocket连接的请求时,自动触发
# 服务端允许和客户端创建连接(握手)
self.accept()
收发消息
收发消息(客户端的向服务端发消息)
客户端
服务端
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
class ChatConsumer(WebsocketConsumer):
def websocket_connect(self, message):
print("有人来连接了....")
# 有客户端来向服务端发送websocket连接的请求时,自动触发
# 服务端允许和客户端创建连接(握手)
self.accept()
def websocket_receive(self, message):
# 浏览器基于websocket向服务端发送数据,自动触发接收客户端消息
print("接收到消息了",message)
收发消息(服务端给客户端发消息)
服务端
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
class ChatConsumer(WebsocketConsumer):
def websocket_connect(self, message):
print("有人来连接了....")
# 有客户端来向服务端发送websocket连接的请求时,自动触发
# 服务端允许和客户端创建连接(握手)
self.accept()
# 服务端给客户端发消息
self.send("来了呀客官") ### 服务端给客户端发消息
客户端