WebSocket协议是基于TCP的一种新的协议。WebSocket最初在HTML5规范中被引用为TCP连接,作为基于TCP的套接字API的占位符。它实现了浏览器与服务器全双工(full-duplex)通信。其本质是保持TCP连接,在浏览器和服务端通过Socket进行通信。

当客户端向服务端发送连接请求时,不仅连接还会发送【握手】信息,并等待服务端响应,至此连接才创建成功!

请求和响应的【握手】信息需要遵循规则:

  • 从请求【握手】信息中提取 Sec-WebSocket-Key
  • 利用magic_string 和 Sec-WebSocket-Key 进行hmac1加密,再进行base64加密
  • 将加密结果响应给客户端

注:magic string为:258EAFA5-E914-47DA-95CA-C5AB0DC85B11

如果返回的结果和客户端的加密结果一致,说明服务端支持websocket请求,连接才能建立成功。

 当服务端想要主动向客户端发送信息的时候,可以考虑使用websocket

客户端和服务端传输数据时,需要对数据进行【封包】和【解包】。很多库已经封装【封包】和【解包】过程,但有些没有进行封装的例如Socket服务端需要手动实现。

根据第二个字节的后7位的大小不同,数据的长度也不同。

   info = conn.recv(8096)

    payload_len = info[1] & 127
if payload_len == 126:
extend_payload_len = info[2:4]
mask = info[4:8]
decoded = info[8:]
elif payload_len == 127:
extend_payload_len = info[2:10]
mask = info[10:14]
decoded = info[14:]
else:
extend_payload_len = None
mask = info[2:6]
decoded = info[6:] bytes_list = bytearray()
for i in range(len(decoded)):
chunk = decoded[i] ^ mask[i % 4]
bytes_list.append(chunk)
body = str(bytes_list, encoding='utf-8')
print(body)

  

Django实现websocket

django channels 是django支持websocket的一个模块。

settings.py

INSTALLED_APPS = [
xxx,
'corsheaders',
'rest_framework',
'channels',
] ASGI_APPLICATION = "big_model_code.asgi.application"
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)], # 你的redis地址和端口
},
},
}

settings.py同级目录下创建asgi.py

假设app为chatOperation,在app下创建routtings.py , 作用等同于urls.py

urls.py处理http请求,routtings.py处理websocket请求

import os

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application from chatOperation.routings import websocket_urlpatterns os.environ.setdefault("DJANGO_SETTINGS_MODULE", "big_model_code.settings") # big_model_code为项目名 application = ProtocolTypeRouter({
"http": get_asgi_application(),
'websocket':AuthMiddlewareStack(URLRouter(websocket_urlpatterns)),
})

chatOperation.routings.py

from django.urls import re_path
from chatOperation import consumers websocket_urlpatterns = [
re_path(r"ws/start/(?P<user_room>\w+)", consumers.PushStream.as_asgi()), # 这里可以定义自己的路由
# 如果是传参的路由在连接中获取关键字参数方法:self.scope['url_route']['kwargs']['user_room']
]

app下创建consumers.py,作用等同于views.py

from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
from asgiref.sync import async_to_sync # 异步转为同步 class PushStream(WebsocketConsumer):
"""推流"""
def websocket_connect(self, message):
#有客户端向后端改善websocket请求时自动触发

#服务端允许执行下行代码,如果不允许可以用 raise StopConsumner()拒绝客户端的连接请求

self.room_name = self.scope['url_route']['kwargs'].get('user_room', 'group1')

# room_group_name 这个是一个分组,最好你主动推送时是要用到这个名字的,所以这个名字命名一定要有点规则,规则自己定义,需要注意的是,这个分组里面是可以放多个连接的,然后推送时,会推送到这个组里面所有用户
self.room_group_name = '%s%s' % (PUSH_RULE,self.room_name)

# 固定写法,加入组,如果组已存在,则加入,不存在,则先创建后加入
async_to_sync(self.channel_layer.group_add)(
self.room_group_name, # 组名
self.channel_name
)

# 开启连接
self.accept() def websocket_receive(self, message):
#客户端发来数据时触发,message是客户端发来的数据(一个字典) text_data_json = json.loads(message)
message = text_data_json['message'] # Send message to room group
async_to_sync(self.channel_layer.group_send)(
self.room_group_name,
{
'type': 'send_message', # 推送消息时调用的方法
'event': message
}
) def send_message(self, event):
    """向某个组推送消息时调用此方法"""
message = event['event']
self.send(message) def websocket_disconnect(self, message):
# 断开连接时触发
async_to_sync(self.channel_layer.group_discard)(
self.room_group_name,
self.channel_name
)
raise StopConsumer()

 

主动推送信息,例如发起了某个http请求,接收到请求就通过websocket推送信息

from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer def handle_push_stream(user,path):
"""推流"""
try:
res = {}
info = {"message":"plug flow success","path":path}
# 发送消息
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
get_rule_room_name(user), # 组名
{
"type": "send_message", # 这个就是你上面 consumers.py 定义的 send_message方法
"event": json.dumps(info) # 是send_message方法接受的参数
}
) res['message'] = 'success'
return res
except:
logger.error(traceback.format_exc())

  

nginx配置

location /ws {
proxy_pass http://127.0.0.1:8999;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name; }

服务器需要通过 daphne -p 端口号 项目名.asgi:application  来启动websocket

例如: daphne -p 8999 big_model_code.asgi:application

模块版本

daphne 3.0.2
Django 3.2.22
django-cors-headers 4.3.0
django-redis 5.4.0

redis  5.0.1

channels 3.0.5
channels-redis 4.1.0

django通过channels实现websocket的更多相关文章

  1. Django使用channels实现Websocket连接

    简述: 需求:消息实时推送消息以及通知功能,采用django-channels来实现websocket进行实时通讯.并使用docker.daphne启动通道,保持websocket后台运行 介绍Dja ...

  2. Django使用Channels实现WebSocket--下篇

    希望通过对这两篇文章的学习,能够对Channels有更加深入的了解,使用起来得心应手游刃有余 通过上一篇<Django使用Channels实现WebSocket--上篇>的学习应该对Cha ...

  3. Django使用Channels实现WebSocket--上篇

    WebSocket - 开启通往新世界的大门 WebSocket是什么? WebSocket是一种在单个TCP连接上进行全双工通讯的协议.WebSocket允许服务端主动向客户端推送数据.在WebSo ...

  4. Django使用channel实现websocket

    channel 什么是channel? channel是第三方工具包,对于不支持websocket协议的框架可以借助此包实现websocket 安装 终端安装: pip3 install channe ...

  5. 6.channels 配置websocket

      Django默认不支持websockey,需要Django支持的话需要安装第三方组件 django channels 是django支持websocket的一个模块.   1.安装 pip3 in ...

  6. Ubuntu + Django(DRF) + channels(websocket)+NGINX + uwsgi 环境部署

    原来uwsgi并不能启动  asgi  呀!现在才知道,就因为这一点我花了一周时间才成功啊!!!!!!!! 是呀!你启动uwsgi 是将你的项目启动了,可是你也发现虽然启动了,但是你的websocke ...

  7. 堡垒机WebSSH进阶之实时监控和强制下线

    这个功能我可以不用,但你不能没有 前几篇文章实现了对物理机.虚拟机以及Kubernetes中Pod的WebSSH操作,可以方便的在web端对系统进行管理,同时也支持对所有操作进行全程录像,以方便后续的 ...

  8. 再聊我们自研的那些Devops工具

    两年前我写了篇文章『我们自研的那些Devops工具』介绍了我们自研的一些DevOps工具系统,两年过去了这些工具究竟还有没有在发光发热,又有哪些新的变化呢,我将通过这篇文章来回顾一下这两年的发展与变化 ...

  9. 实时 Django 终于来了 —— Django Channels 入门指南

    Reference: http://www.oschina.net/translate/in_deep_with_django_channels_the_future_of_real_time_app ...

  10. django + nginx + uwsgi + websocket

    最近使用django框架做了一个简单的聊天机器人demo, 开发的过程中使用了django自带的websocket模块,当使用django框架自带的wsgi服务去启动的话,没有什么问题.如果要使用uw ...

随机推荐

  1. MySQL统计信息不准导致的性能问题

    简介: 统计信息不准导致错误的执行计划,引发性能问题 表的统计信息错误导致优化器选择错误的执行计划. 一个客户的性能优化案例: 没有修改数据库实例的任何配置参数以及业务代码没有变更的情况下,一条 sq ...

  2. KubeVela v1.2 发布:你要的图形化操作控制台 VelaUX 终于来了!

    ​简介:时间来到 2022 年,KubeVela 也正式进入了第四个阶段,在原先核心控制器 API 基本稳定的基础上,我们以插件的形式增加了一系列开箱即用的功能.让开发者可以通过 UI 控制台的方式, ...

  3. 通用的 AI prompt 实操技巧

    1. 提供清晰.具体的目标在 Prompt 中明确指出你希望 AI 辅助完成的具体任务,包括要实现的功能.遵循的标准.适用的技术栈等. 2. 提供足够的上下文提供与任务相关的背景信息.现有代码片段.接 ...

  4. dotnet 推荐 LightWorkFlowManager 轻量的工作过程管理库

    本文将和大家推荐我团队开源的 LightWorkFlowManager 轻量的工作过程管理库,适合任何需要执行工作过程的应用逻辑,可以方便将多个工作过程拼凑起来,且自动集成重试和失败处理,以及日志和上 ...

  5. WPF 关于将 ManipulationDeltaEventArgs 的 Manipulators 属性返回值修改为 ReadOnlyCollection 类型的提议

    这是一个 WPF 框架的 API 变更提议,记录一下博客 讨论的地方是: How about change the type of ManipulationDeltaEventArgs.Manipul ...

  6. dotnet 开启 Fiddler 抓包将会让请求 HOST 头被更改

    我在写域名备份功能,想要修改请求的 IP 地址,同时又将原有的请求域名带上.实现方法是修改请求的地址,在 HttpRequestMessage 的 Header 上添加 HOST 记录,记录的值就是原 ...

  7. Unsortbin attack原理及分析

    Unsortbin attack原理 ️条件:首先要实现Unsortbin attack前提是可以控制Unsortbin attack chunk的bk指针 ️目的:我们可以实现修改任意地址为一个比较 ...

  8. Typora+免费图床,构建随处可用的Markdown文档

    Typora+PicGo+Gitee自动上传图片 视频教程: https://www.bilibili.com/video/BV1hT4y1f7Mf?from=search&seid=1546 ...

  9. 🔥httpsok-v1.11.0支持CDN证书自动部署

    httpsok-v1.11.0支持CDN证书自动部署 介绍 httpsok 是一个便捷的 HTTPS 证书自动续签工具,专为 Nginx .OpenResty 服务器设计.已服务众多中小企业,稳定.安 ...

  10. kettle使用1-全表导入

    1.新建转换 2.DB连接中,新建数据库连接 3.在输入中,选择表输入 选择连接的数据库和查询的sql的数据 4.再输出中,选择表输出 5.按住shift,建立数据连接 6.匹配数据字段映射