Django使用channels实现Websocket连接
简述:
需求:消息实时推送消息以及通知功能,采用django-channels来实现websocket进行实时通讯。并使用docker、daphne启动通道,保持websocket后台运行
介绍Django Channels:
官方文档链接:https://channels.readthedocs.io/en/latest/introduction.html
#参考 Django Channels 的docs文档
通道包装了Django的本机异步视图支持,允许Djangoprojects不仅处理HTTP,还处理需要长时间运行的连接的协议——网络套接字、MQTT、聊天机器人、业余无线电等等。
它做到了这一点,同时保留了Django的同步和易于使用的特性,允许您选择如何编写代码——以Django视图的方式同步,完全异步,或者两者兼而有之。
除此之外,它还提供了与Django的授权系统、会话系统等的集成,使得将您的纯HTTP项目扩展到其他协议比以往任何时候都更容易
#channels由几个包组成:
Channels,Django集成层
Daphne,HTTP和Websocket终止服务器
asgiref,基本ASGI库
channels_redis,Redis通道层后端(可选)
依赖性:
这里假设你的django版本是3.0以上,所有channels项目目前都支持Python 3.6及更高版本。
channels与Django 2.2、3.0和3.1兼容。如果你的django版本是2.2或以下,相关配置请查看官网。
安装django channels:
pip install -U channels #pip 安装需要加上-U
Django项目设置:
#setting.py添加内容
将Channels库添加到已安装的应用程序列表中。编辑 settings.py 文件,并将channels添加到INSTALLED_APPS设置中。
INSTALLED_APPS = [
'channels', #在这里添加,请保持channels在第一项
'appname',
]
ASGI_APPLICATION = "myproject.asgi.application" #就这样!一旦启用,通道将自己集成到Django中并控制runserver命令
运行python manage.py runserver 命令:
System check identified no issues (0 silenced).
December 18, 2020 - 09:14:59
Django version 3.1.2, using settings 'myproject.settings'
Starting ASGI/Channels version 3.0.2 development server at http://127.0.0.1:8000/ #<<<请注意这行与之前的区别
Quit the server with CTRL-BREAK.
描述WSGI与ASGI:
篇幅原因,请参看另一篇博文:https://www.cnblogs.com/mqlwyz/p/14149945.html
逻辑代码
#创建默认路由(主WS路由)
WS(WebSocket )是不安全的 ,容易被窃听,因为任何人只要知道你的ip和端口,任何人都可以去连接通讯。
WSS(Web Socket Secure)是WebSocket的加密版本。
所以建议使用WSS,这是测试版使用的是WS
通道提供了对常见Django特性(如会话和身份验证)的轻松插入支持。只需在WebSocket视图周围添加适当的中间件,就可以将身份验证与WebSocket视图结合起来
在myproject/myproject下创建routing.py:
from channels.routing import ProtocolTypeRouter,URLRouter
import os
from channels.auth import AuthMiddlewareStack
import appadmin.routing
from django.core.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")
django_asgi_app = get_asgi_application()
application = ProtocolTypeRouter({
# (your routes here)
'http' : django_asgi_app,
'websocket': AuthMiddlewareStack(
URLRouter(
appname.routing.websocket_urlpatterns
)
)
})
django2.2配置:
注:Django 2.2没有内置的ASGI支持,所以我们需自行在myproject/myproject下创建asgi.py:
import os
import django
from channels.routing import get_default_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
django.setup()
application = get_default_application()
使用Docker安装和运行Redis:
我们使用Redis作为channel层的后备存储,这是我们在本教程中使用的Channels库的可选组件。从Docker的官方网站上
安装Docker——有MacOS和Windows的官方运行时,使其易于使用,并且有许多Linux发行版的软件包,可以在本地运行。
#注:使用的通道功能将需要Redis来运行,建议Docker是实现这一点的最简单方法。
我们将使用一个使用Redis作为后台存储的通道层。要在端口6379上启动Redis服务器,请运行以下命令:
docker run -p 6379:6379 -d redis:5
参照图片:
使用运行协议服务器>Daphne:
注:Daphne是一个纯Python ASGI服务器,由Django项目的成员维护。它充当ASGI的参考服务器。
不过django官网上就寥寥几句话:>>>https://docs.djangoproject.com/zh-hans/3.0/howto/deployment/asgi/daphne/
#安装 Daphne
python -m pip install daphne
为了与外界对话,需要将Channels/ASGI应用程序加载到协议服务器中。它们可以像WSGI服务器一样,以HTTP模式运行应用程序,但它们也可以连接到任何数量的其他协议(聊天协议、物联网协议、甚至无线网络)。
所有这些服务器都有自己的配置选项,但它们都有一个共同点——它们希望您向它们传递一个ASGI应用程序来运行。您只需在项目的asgi.py公司将文件作为它应该运行的应用程序发送到协议服务器:
daphne -b 127.0.0.1 -p 8001 myproject.asgi:application #使用daphne需单独安装redis,并配置添加windos服务,C:\Windows\System32\drivers\etc\hosts添加redis的ip地址,默认是127.0.0.1
运行之后成功参考如下代码:
(venv) D:\myproject>daphne -b 127.0.0.1 -p 8001 myproject.asgi:application #在你myproject项目下的文件下执行命令
2020-12-18 09:15:55,042 INFO Starting server at tcp:port=8001:interface=127.0.0.1
2020-12-18 09:15:55,042 INFO HTTP/2 support not enabled (install the http2 and tls Twisted extras)
2020-12-18 09:15:55,043 INFO Configuring endpoint tcp:port=8001:interface=127.0.0.1
2020-12-18 09:15:55,050 INFO Listening on TCP address 127.0.0.1:8001
我们需要知道如何安装redis频道。运行以下命令:
pip install -U channels_redis
验证通道是否开启的方法:
使用win + r 打开cmd,输入:
telnet 127.0.0.1 6379 #6379为端口号,请使用相应的端口测试
telnet通的情况如下:
在使用通道层之前,我们必须对其进行配置。编辑myproject/setting.py文件并在底部添加一个CHANNEL_LAYERS设置。它应该看起来像:
# myproject/settings.py
# Channels
ASGI_APPLICATION = "myproject.asgi.application" #这是之前在setting设置过的,不要重复
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
'hosts': [
('localhost', 6379), #可以配置多个通道层。然而,大多数项目将只使用一个“默认”通道层。
#如果你是使用Docker安装运行redis的请注释下面的配置
('redis_server_name', 6379),
#如果你是使用Daphne运行的请注释掉localhost那一行配置
],
},
},
}
现在我们有了一个通道层,让我们在chatcustomer中使用它。在chat中输入以下代码appname/consumers.py,代码如下:
# appname/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.room_name
# Join room group
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
# Leave room group
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
# Receive message from WebSocket
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
# Send message to room group
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'message': message
}
)
# Receive message from room group
async def chat_message(self, event):
message = event['message']
# Send message to WebSocket
await self.send(text_data=json.dumps({
'message': message
}))
注:ChatConsumer现在继承了AsyncWebsocketConsumer而不是WebsocketConsumer。所有方法都是异步def,而不仅仅是def。
await用于调用执行I/O的异步函数。在通道层上调用方法时,不再需要异步同步。
应用下创建 routing.py (类似Django路由)
from django.urls import path
from appadmin import consumers
websocket_urlpatterns = [
# url(r'^ws/msg/(?P<room_name>[^/]+)/$', consumers.SyncConsumer),
path("ws/test_async" , consumers.ChatConsumer.as_asgi()),
]
前端页面连接Websockct:
templates下新建test/test.html
注:需正常在urls.py添加路由
<<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Websocket测试</title>
<link rel="stylesheet" href="/static/layui/css/layui.css" media="all">
<script src="http://cdn.bootcss.com/jquery/1.12.3/jquery.min.js"></script>
<script src="/static/layui/layui.js"></script>
</head>
<body style="margin: auto">
<script>
if ("WebSocket" in window) {
// 打开一个 web socket
var ws = new WebSocket(+ window.location.host + "/ws/test_async");
console.log("ws:" + window.location.host + "/ws/test_async")
console.log('ws',ws)
ws.onopen = function () {
// Web Socket 已连接上,使用 send() 方法发送数据
alert("链接成功")
ws.send("发送消息");
console.log('onopen')
{#alert("数据发送中...");#}
};
ws.onmessage = function (evt) {
var received_msg = evt.data;
{#alert("数据已接收...");#}
console.log("数据:" + received_msg)
};
ws.onclose = function () {
// 关闭 websocket
alert("链接关闭,请重试")
console.log("连接已关闭...");
};
}
else {
// 浏览器不支持 WebSocket
alert("您的浏览器不支持 WebSocket!");
}
</script>
网页上访问
输入127.0.0.1:8000/test.html
按F12,查看console选项:
或提示消息:
Django使用channels实现Websocket连接的更多相关文章
- vue+django实现websocket连接
一.概述 在项目中,需要使用websocket,来展示一些实时信息. 这里使用django 3.1.5 二.django项目 安装模块 pip3 install django-cors-headers ...
- Django使用Channels实现WebSocket--下篇
希望通过对这两篇文章的学习,能够对Channels有更加深入的了解,使用起来得心应手游刃有余 通过上一篇<Django使用Channels实现WebSocket--上篇>的学习应该对Cha ...
- Django使用Channels实现WebSocket--上篇
WebSocket - 开启通往新世界的大门 WebSocket是什么? WebSocket是一种在单个TCP连接上进行全双工通讯的协议.WebSocket允许服务端主动向客户端推送数据.在WebSo ...
- 6.channels 配置websocket
Django默认不支持websockey,需要Django支持的话需要安装第三方组件 django channels 是django支持websocket的一个模块. 1.安装 pip3 in ...
- Django使用channel实现websocket
channel 什么是channel? channel是第三方工具包,对于不支持websocket协议的框架可以借助此包实现websocket 安装 终端安装: pip3 install channe ...
- 使用wireshark抓包分析浏览器无法建立WebSocket连接的问题(server为Alchemy WebSockets组件)
工作时使用了Websocket技术,在使用的过程中发现,浏览器(Chrome)升级后可能会导致Websocket不可用,更换浏览器后可以正常使用. 近日偶尔一次在本地调试,发现使用相同版本的Chrom ...
- 使django与数据库保持长连接
最近遇到一个很蛋疼的问题,写了一个后台管理系统, 由于是后台管理系统,所以使用频率不是很高,当django程序在闲置一段时间后,再次打开后台系统,就变得很慢,然后又好了.查了很多方面,从模板引擎到请求 ...
- 7.1.1.关闭WebSocket连接
7.1.定义 7.1.1.关闭WebSocket连接 为_关闭WebSocket连接_,端点需关闭底层TCP连接.端点应该使用一个方法完全地关闭TCP连接,以及TLS会话,如果合适,丢弃任何可能已经接 ...
- 学习html5的WebSocket连接
1.什么是WebSocket WebSocket 是一种自然的全双工.双向.单套接字连接.使用WebSocket,你的HTTP 请求变成打开WebSocket 连接(WebSocket 或者WebSo ...
随机推荐
- C++深拷贝与浅拷贝区别
浅拷贝只是对指针的拷贝,浅拷贝后两个指针指向同一个内存空间: 深拷贝不仅对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针. 当对一个已知对象进行拷贝时,编译系统会 ...
- 制作视频教程,用Camtasia你也可以
一直以来,每当我在电脑使用过程中有不会的地方,往往我就会通过百度或者b站寻找教程,尤其是视频教程来学习,这样我往往就可以快速的学会相应的操作.当朋友在qq或者微信问我们一些操作时,我们却不能向他们提供 ...
- Requests 库的使用
Python 的标准库 urllib 提供了大部分 HTTP 功能,但使用起来较繁琐.通常,我们会使用另外一个优秀的第三方库:Requests,它的标语是:Requests: HTTP for Hum ...
- pip递归安装报错继续安装
使用命令pip freeze > requirements.txt导出项目依赖包之后,使用pip -r requirements.txt的时候可能会出现一些包安装出错,但是安装一旦出错,安装就会 ...
- 华为模拟器ensp老是弹出一堆英文up down,关闭
英文内容: Mar 25 2015 20:38:21-08:00 Huawei DS/4/DATASYNC_CFGCHANGE:OID 1.3.6.1.4.1.2011.5.25.191.3.1 co ...
- 03_Service的绑定
Start Service启动的Service,Application退出,Service也不会退出: Bind Service启动的Service,Application退出,Service就会退出 ...
- 更改ubuntu的分辨率
乘号使用xyz的x打出来
- Sql注入--数字型手工测试
Sql注入--数字型手工测试 漏洞原因:是在数据交互中,前端的数据传入到后台处理时,没有做严格的判断,导致其传入的"数据"拼接到SQL语句中后,被当作SQL语句的一部分执行. 从而 ...
- PyQt(Python+Qt)学习随笔:QTableView的标题表头相关属性
老猿Python博文目录 老猿Python博客地址 一.概述 在Qt Designer中,对于表视图QTableView,在属性在下面有专门一栏列出了跟标题相关的属性,如图: 这些属性并不是QTabl ...
- hitorMiss、hitAndMiss以及MORPH_HITMISS?
hitorMiss.hitAndMiss在图像处理中都是同一个概念,即图像的形态学变换中的击中击不中变换,hit表示击中,miss表示击不中.MORPH_HITMISS是OpenCV调用时该变换的op ...