Django中如何使用Channels功能

目录
  • 一、什么是WebSocket
  • 二、什么是Channels
  • 三、Django中使用Channel
  • 四、前端Websocket使用
  • 五、测试Channels功能      

前言:最近后台写游戏更新版本功能,简单就是前端发送更新请求,后端需要对很多台服务器进行更新和各种操作,本来想着实现不难,后来发现因为后端需要执行很长时间,前端返回报错,后端会执行完毕,但是前端先断开了,这样在前端页面我就看不到更新结果了。通过调整nginx参数,设置超时时间,还是日志会报499状态码错误。后来了解到了websocket,对于需要长时间处理的请求,使用websocket会更好,通过使用websocket实现了自己的功能,简单分享下

一、什么是WebSocket

WebSocket是一种在单个TCP连接上进行全双工通讯的协议。WebSocket允许服务端主动向客户端推送数据。
在WebSocket协议中,客户端浏览器和服务器只需要完成一次握手就可以创建持久性的连接,并在浏览器和服务器之间进行双向的数据传输。

WebSocket的响应头中重要的字段:
HTTP/1.1 101 Swi tching Protocols:切换协议,WebSocket协议通过HTTP协议来建立运输层的TCP连接
Connection和Upgrade:表示服务端发起的WebSocket响应
Sec-WebSocket-Accept:表示服务器接受了客户端的请求,由Sec-WebSocket-Key计算得来

WebSocket协议的优点:
支持双向通信,实时性更强
数据格式比较轻量,性能开销小,通信高效
支持扩展,用户可以扩展协议或者实现自定义的子协议(比如支持自定义压缩算法等)

WebSocket协议的缺点:
少部分浏览器不支持,浏览器支持的程度与方式有区别
长连接对后端处理业务的代码稳定性要求更高,后端推送功能相对复杂
成熟的HTTP生态下有大量的组件可以复用,WebSocket较少

WebSocket的应用场景:
即时聊天通信,网站消息通知
在线协同编辑,如腾讯文档
多玩家在线游戏,视频弹幕,股票基金实施报价

二、什么是Channels

Django本身不支持WebSocket,但可以通过集成Channels框架来实现WebSocket
Channels是针对Django项目的一个增强框架,可以使Django不仅支持HTTP协议,还能支持WebSocket,MQTT等多种协议,同时Channels还整合了Django的auth以及session系统方便进行用户管理及认证。

2.1channels文件和配置的含义

asgi.py:介于网络协议服务和Python应用之间的接口,能够处理多种通用协议类型,包括HTTP、HTTP2和WebSocket
channel_layers:在settings.py中配置。类似于一个通道,发送者(producer)在一段发送消息,消费者(consumer)在另一端进行监听
routings.py:相当于Django中的urls.py
consumers.py:相当于Django中的views.py

2.2channels文档链接

https://channels.readthedocs.io/en/latest/introduction.html

2.3.WSGI和ASGI不同

WSGI(Python Web Server Gateway Interface):为Python语言定义的Web服务器和Web应用程序或者框架之间的一种简单而通用的接口。

ASGI(Asynchronous Web Server Gateway Interface):异步网关协议接口,一个介于网络协议服务和Python应用之间的标准接口,能够处理多种通用的协议类型,包括HTTP,HTTP2和WebSocket。

三、Django中使用Channel

3.1安装channels

pip install channels==2.1.7

3.2修改setting.py文件

INSTALLED_APPS = [
    'django.contrib.staticfiles',
    ... ...
    'channels',
]

# 指定ASGI的路由地址
ASGI_APPLICATION = 'webapp.routing.application' #ASGI_APPLICATION 指定主路由的位置为webapp下的routing.py文件中的application

3.3setting.py的同级目录下创建routing.py路由文件,routing.py类似于Django中的url.py指明websocket协议的路由

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
import webapp.routing

application = ProtocolTypeRouter({
    'websocket':AllowedHostsOriginValidator(
        AuthMiddlewareStack(
            URLRouter(
                webapp.routing.websocket_urlpatterns
            )
        )
    )
})

ProtocolTypeRouter:ASGI支持多种不同的协议,在这里可以指定特定协议的路由信息,这里只使用了websocket协议,这里只配置websocket即可
AllowedHostsOriginValidator:指定允许访问的IP,设置后会去Django中的settings.py中去查找ALLOWED_HOSTS设置的IP
AuthMiddlewareStack:用于WebSocket认证,继承了Cookie Middleware,SessionMiddleware,SessionMiddleware。
django的channels封装了django的auth模块,使用这个配置我们就可以在consumer中通过下边的代码获取到用户的信息,和请求的url路径

self.sc

def connect(self):
    self.user = self.scope["user"]
    self.request_url = self.scope['path']

ope类似于django中的request,包含了请求的type、path、header、cookie、session、user等等有用的信息
URLRouter: 指定路由文件的路径,也可以直接将路由信息写在这里,代码中配置了路由文件的路径,会去对应应用下的routeing.py文件中查找websocket_urlpatterns

3.4webapp.routing.py内容如下

from django.urls import path
from webapp.consumers import ChatConsumer

websocket_urlpatterns = [
  path('ws/chat/',ChatConsumer)
]

routing.py路由文件跟django的url.py功能类似,语法也一样,意思就是访问ws/chat/都交给ChatConsumer处理。  

3.5在要使用WebSocket的应用中创建consumers.py,consumers.py是用来开发ASGI接口规范的python应用,而Django中的view.py是用来开发符合WSGI接口规范的python应用。  

from channels.generic.websocket import WebsocketConsumer
from channels.generic.websocket import AsyncWebsocketConsumer
import json,time

Channels支持同步,也支持异步方式

同步方式代码如下:

class ChatConsumer(WebsocketConsumer):
    # websocket建立连接时执行方法
    def connect(self):
        self.accept()

    # websocket断开时执行方法
    def disconnect(self, close_code):
        self.close()

    # 从websocket接收到消息时执行函数
    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = f'结果:{text_data_json}'
        self.send(text_data=json.dumps(
        {
             'message': message
        }))

异步方式代码如下:

class ChatConsumer(AsyncWebsocketConsumer):
    #websocket建立连接时执行方法
    async def connect(self):
        await self.accept()

    # websocket断开时执行方法
    async def disconnect(self, close_code):
        print(close_code)

    # 从websocket接收到消息时执行函数
    async def receive(self, text_data):
        for i in range(10):
            time.sleep(i)
            message = '结果: ' + str(i)
            await self.send(text_data=json.dumps({
                'message': message
            })
        )

需要注意的是在异步中所有的逻辑都应该是异步的,不可以那同步的和异步的代码混合使用。  

四、前端Websocket使用

WebSocket对象一个支持四个消息:onopen,onmessage,oncluse和onerror

onopen: 当浏览器和websocket服务端连接成功后会触发onopen消息
onerror: 如果连接失败,或者发送、接收数据失败,或者数据处理出错都会触发onerror消息
onmessage: 当浏览器接收到websocket服务器发送过来的数据时,就会触发onmessage消息,参数e包含了服务端发送过来的数据
onclose: 当浏览器接收到websocket服务器发送过来的关闭连接请求时,会触发onclose消息

拼接websocket请求地址,建立长连接

var chatSocket = new WebSocket('ws://' + window.location.host + '/ws/ver_update/');

连接事件  

chatSocket.onopen = function () {
    console.log(getCurrentDate(2) + ' ' + 'websocket connection success')
};

错误事件

chatSocket.onerror = function () {
    console.error(getCurrentDate(2) + ' ' + 'websocket connection error')
};

关闭事件

chatSocket.onclose = function (e) {
    layer.msg('websocket关闭,检查错误日志', {icon: 2});
    console.error(getCurrentDate(2) + ' ' + 'websocket closed unexpectedly 状态码:' + e.code);
    chatSocket.close();
};

接收事件

chatSocket.onmessage = function (e) {
    var data = JSON.parse(e.data);
}

五、测试Channels功能      

总结:自从使用Websocket功能后,再也没发生前端突然断开的情况了,对于长时间运行的任务,使用websocket是不错的选择~,有不足的地方请多多指教  

到此这篇关于Django中使用Channels功能的文章就介绍到这了,更多相关Django使用Channels内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • django使用channels实现通信的示例

    1.安装依赖包 pip install channels channels-redis 2.settings.py 修改加上支持 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'MyW

  • django使用channels2.x实现实时通讯

    一.背景 在最近的项目中的一个需求是消息实时推送消息以及通知功能,项目使用django写的所以决定采用django-channels来实现websocket进行实时通讯.目前官方已经更新到2.1版本,相对于老的channels 1.x版本有了很大变化,无论是使用方式还是功能,其中最大的变化莫过于2.x版本中带来的asyncio特性,可使用异步处理模式.本文内容将介绍channels2版本使用,由于项目django是1.11,其中也遇到了一些坑,比如在channels在处理一次请求后hang住然后

  • 详解Django-channels 实现WebSocket实例

    引入 先安装三个模块 pip install channels pip install channels_redis pip install pywin32 创建一个Django项目和一个app 项目名随意,app名随意.这里项目名为 django_websocket_demo ,app名 chat 把app文件夹下除了 views.py 和 __init__.py 的文件都删了,最终项目目录结构如下: django_websocket_demo/ manage.py django_websoc

  • Django使用Channels实现WebSocket的方法

    WebSocket - 开启通往新世界的大门 WebSocket是什么? WebSocket是一种在单个TCP连接上进行全双工通讯的协议.WebSocket允许服务端主动向客户端推送数据.在WebSocket协议中,客户端浏览器和服务器只需要完成一次握手就可以创建持久性的连接,并在浏览器和服务器之间进行双向的数据传输. WebSocket有什么用? WebSocket区别于HTTP协议的一个最为显著的特点是,WebSocket协议可以由服务端主动发起消息,对于浏览器需要及时接收数据变化的场景非常

  • Django使用channels + websocket打造在线聊天室

    Channels是Django团队研发的一个给Django提供websocket支持的框架,它同时支持http和websocket多种协议.使用channels可以让你的Django应用拥有实时通讯和给用户主动推送信息的功能. 演示效果如下所示: 什么是websocket? WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议.WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据.在 WebSocket API

  • Django Channels 实现点对点实时聊天和消息推送功能

    简介在很多实际的项目开发中,我们需要实现很多实时功能:而在这篇文章中,我们就利用django channels简单地实现了点对点聊天和消息推送功能. 手边有一个项目需要用到后台消息推送和用户之间一对一在线聊天的功能.例如用户A评论了用户B的帖子,这时候用户B就应该收到一条通知,显示自己的帖子被评论了.这个功能可以由最基本的刷新页面后访问数据库来完成,但是这样会增加对后台服务器的压力,同时如果是手机客户端的话,也会造成流量的损失.于是,我们考虑使用websocket建立一个连接来完成这个功能. 但

  • 浅谈django channels 路由误导

    与django路由有区别 他们都有根路由,但是不一样. django的根路由: urlpatterns = [ path('login/',include('login.urls')), path('',views.home), path('helloapp/', include('helloapp.urls')), path('admin/', admin.site.urls), ] channels的根路由: 只能形如这种样子,URLRouter里面是一个列表,列表当中是具体路由条目. ap

  • Django中如何使用Channels功能

    目录 一.什么是WebSocket 二.什么是Channels 三.Django中使用Channel 四.前端Websocket使用 五.测试Channels功能 前言:最近后台写游戏更新版本功能,简单就是前端发送更新请求,后端需要对很多台服务器进行更新和各种操作,本来想着实现不难,后来发现因为后端需要执行很长时间,前端返回报错,后端会执行完毕,但是前端先断开了,这样在前端页面我就看不到更新结果了.通过调整nginx参数,设置超时时间,还是日志会报499状态码错误.后来了解到了websocket

  • django中的图片验证码功能

    python的验证码库(captcha) 将验证码做成这样: 是不是和各大网页的图片源地址是一样,话不多说,让我们看代码: 我是用django和python中的captcha库做成 的 创建一个captcha_image.py: from captcha.image import ImageCaptcha import random class Captcha_Get(): def __init__(self, CHAR_SET = ['0', '1', '2', '3', '4', '5',

  • Django 中自定义 Admin 样式与功能

    Django 中自定义 Admin 样式与功能 自定义 Admin 样式与功能 1 页面修改中文 1.1 语言设置为中文 settings.py LANGUAGE_CODE = 'zh-hans' 修改结果 1.2 应用管理设置为中文 应用/apps.py from django.apps import AppConfig class BbssConfig(AppConfig):     name = 'bbs'     # 添加下面这句     verbose_name = 'BBS系统' 修

  • django中账号密码验证登陆功能的实现方法

    今天分享一下django的账号密码登陆,前端发送ajax请求,将用户名和密码信息发送到后端处理,后端将前端发送过来的数据跟数据库进行过滤匹配,成功就跳转指定页面,否则就把相对应的错误信息返回,同时增加一个小功能,在规定时间内超过规定的登录次数,就锁住无法登陆,等下一个时间段再允许登陆. 一.通过ORM创建一张历史登陆表 class login_history(models.Model): user = models.CharField(max_length=32, verbose_name='登

  • django中使用事务及接入支付宝支付功能

    之前一直想记录一下在项目中使用到的事务以及支付宝支付功能,自己一直犯懒没有完,趁今天有点兴致,在这记录一下. 商城项目必备的就是支付订单的功能,所以就会涉及到订单的保存以及支付接口的引入.先来看看订单的保存,在数据库模型涉及之初,将订单分成了两个表,一个为订单表,记录订单的基本信息,如订单号,用户信息,运费之类,一个为订单商品表,记录该订单中的商品信息.在保存订单时,肯定会涉及到两个表的新建和保存,其实还有一张表也需要进行一些修改,那就是商品表,当一个订单保存成功,意味着本次交易成功,商品售出,

  • 如何在django中添加日志功能

    官方文档 猛戳这里 在settings中配置以下代码 #LOGGING_DIR 日志文件存放目录 LOGGING_DIR = "logs" # 日志存放路径 if not os.path.exists(LOGGING_DIR): os.mkdir(LOGGING_DIR) import logging LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { #格式化器 'standard'

  • Django 中自定义 Admin 样式与功能的实现方法

    自定义 Admin 样式与功能 1 页面修改中文 1.1 语言设置为中文 settings.py LANGUAGE_CODE = 'zh-hans' 修改结果 1.2 应用管理设置为中文 应用/apps.py from django.apps import AppConfig class BbssConfig(AppConfig): name = 'bbs' # 添加下面这句 verbose_name = 'BBS系统' 修改结果 1.3 数据库表设置为中文 应用/models.py class

  • 如何在django中实现分页功能

    1.在html页面中导入js文件和css文件 <link rel="stylesheet" href="../../../static/css/jquery.pagination.css" rel="external nofollow" > <script type="text/javascript" src="../../../static/js/jquery-1.12.4.min.js"

  • Django中使用pillow实现登录验证码功能(带刷新验证码功能)

    首先在项目里建立common目录,编写验证码的函数 verification_code.py import random from PIL import Image, ImageFont, ImageDraw def get_code(): mode = 'RGB' bg_width = 180 #这个是验证码那个框框的宽度 bg_height = 30 #这个是验证码那个框框的高度 bg_size = (bg_width, bg_height) bg_color = (255, 255, 25

  • 深入探究Django中的Session与Cookie

    前言 Cookie和Session相信对大家来说并不陌生,简单来说,Cookie和Session都是为了记录用户相关信息的方式,最大的区别就是Cookie在客户端记录而Session在服务端记录内容. 那么Cookie和Session之间的联系是怎么建立的呢?换言之,当服务器接收到一个请求时候,根据什么来判断读取哪个Session的呢? 对于Django默认情况来说,当用户登录后就可以发现Cookie里有一个sessionid的字段,根据这个key就可以取得在服务器端记录的详细内容.如果将这个字

随机推荐