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. 零信任策略下K8s安全监控最佳实践(K+)

    简介: 本文重点将围绕监控防护展开,逐层递进地介绍如何在复杂的分布式容器化环境中借助可观测性平台,持续监控K8s集群,及时发现异常的 API 访问事件.异常流量.异常配置.异常日志等行为,并且结合合理 ...

  2. 从托管到原生,MPP架构数据仓库的云原生实践

    ​简介:本文介绍了云原生数据仓库产品AnalyticDB PostgreSQL从Cloud-Hosted到Cloud-Native的演进探索,探讨为了实现真正的资源池化和灵活售卖的底层设计和思考,涵盖 ...

  3. 分久必合的Lindorm传奇

    简介: 2009年,阿里巴巴首先提出用分布式架构替代传统商业数据库,成功用自主开源的AliSQL支撑双11数据洪流:2016年,为应对超大规模业务场景,阿里云开始自研分布式数据库.十余年间,阿里巴巴数 ...

  4. 形式化验证工具TLA+:程序员视角的入门之道

    ​简介: 女娲是飞天分布式系统中提供分布式协同的基础服务,支撑着阿里云的计算.网络.存储等几乎所有云产品.在女娲分布式协同服务中,一致性引擎是核心基础模块,支持了Paxos,Raft,EPaxos等多 ...

  5. 基于英特尔® 优化分析包(OAP)的 Spark 性能优化方案

    ​简介: Spark SQL 作为 Spark 用来处理结构化数据的一个基本模块,已经成为多数企业构建大数据应用的重要选择.但是,在大规模连接(Join).聚合(Aggregate)等工作负载下,Sp ...

  6. python语言中的装饰器详解

        装饰器是一个用于封装函数或类的代码的工具.它显式地将封装器应用到函数或类上,从而使它们选择加入到装饰器的功能中.对于在函数运行前处理常见前置条件(例如确认授权),或在函数运行后确保清理(例如输 ...

  7. IIncrementalGenerator 获取引用程序集的所有类型

    本文告诉大家如何在使用 IIncrementalGenerator 进行增量的 Source Generator 生成代码时,如何获取到当前正在分析的程序集所引用的所有的程序集,以及引用的程序集里面的 ...

  8. 面向教师的OBS直播速成教程

    引言 本文是面向教师讲述的如何使用OBS软件进行课程直播的速成教程. 本文配套视频链接如下️ 面向教师的OBS直播教学速成教程_哔哩哔哩_bilibili 环境准备 1. 下载对应本机系统版本的并安装 ...

  9. linux 下jq的使用

    安装: yum install jq -y 文档: https://stedolan.github.io/jq/manual/ 更多: https://blog.csdn.net/Cheat11730 ...

  10. gin 单个文件函数 上传文件到本地目录里

    // 单个文件 上传文件到本地目录里 // 调用方法 utils.UplaodFileToLocal(c) // author haima func UplaodFileToLocal(c *gin. ...