Django channels

Django channels

  • http是一个网络协议(五状态短连接)
  • https是一个网络协议(五状态短连接)
  • websocket是一个网络协议(让浏览器和服务端创建链接支持,默认不再断开,两端就可以完成相互之间的收发数据)
  • websocket协议的诞生,可以让我们真正实现服务端向客户端推送消息

websocket实现原理:
——握手环节,验证服务端是否支持websocket协议,浏览器生成一个随机字符串,将随机字符串发送给服务端,服务端接收到随机字符串之后,让他跟magic string拼接,然后再进行sha1/base64加密,将密文返回到用户浏览器,用户浏览器会自动进行校验

——收发数据,密文 数据解密时需要读取数据第2个字节的后7位,和127,126,125比较后看情况~~

django channels 是django支持websocket的一个模块。在channels的内部已经帮我们写了握手/加密/解密等所有环节。建议在python3.6的环境中去运行。

1. 安装

pip3 install channels==2.3

2. 快速上手

2.1 在settings中添加配置

 

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'channels',
]
注册channels的app

 

 

ASGI_APPLICATION = "channel_demo.routing.application"
添加ASGI_APPLICATION支持websocket

 

2.2 创建websocket应用和路由

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from channels.routing import ProtocolTypeRouter, URLRouter
from django.conf.urls import url
from chat import consumers


application = ProtocolTypeRouter({
    'websocket': URLRouter([
        url(r'^chat/$', consumers.ChatConsumer),
    ])
})
应用和路由

 

2.3 编写处理websocket逻辑业务

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer

class ChatConsumer(WebsocketConsumer):

    def websocket_connect(self, message):
        self.accept()

    def websocket_receive(self, message):
        print('接收到消息', message)
        self.send(text_data='收到了')

    def websocket_disconnect(self, message):
        print('客户端断开连接了')
        raise StopConsumer()
示例一

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer


class SimpleChatConsumer(WebsocketConsumer):
    def connect(self):
        self.accept()

    def receive(self, text_data=None, bytes_data=None):
        self.send(text_data)

        # 主动断开连接
        # self.close()

    def disconnect(self, code):
        print('客户端要断开了')
示例二
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer


CLIENTS = []

class ChatConsumer(WebsocketConsumer):

    def connect(self):
        self.accept()
        CLIENTS.append(self)

    def receive(self, text_data=None, bytes_data=None):
        for item in CLIENTS:
            item.send(text_data)

        # 主动断开连接
        # self.close()

    def disconnect(self, code):
        CLIENTS.remove(self)
示例三

 

3. channel layer

基于内存的channel layer

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels.layers.InMemoryChannelLayer",
    }
}
配置
from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync


class ChatConsumer(WebsocketConsumer):

    def connect(self):
        async_to_sync(self.channel_layer.group_add)('x1', self.channel_name)
        self.accept()

    def receive(self, text_data=None, bytes_data=None):
        async_to_sync(self.channel_layer.group_send)('x1', {
            'type': 'xxx.ooo',
            'message': text_data
        })

    def xxx_ooo(self, event):
        message = event['message']
        self.send(message)

    def disconnect(self, code):
        async_to_sync(self.channel_layer.group_discard)('x1', self.channel_name)
业务处理

基于 redis的channel layer

pip3 install channels-redis
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [('10.211.55.25', 6379)]
        },
    },
}


CHANNEL_LAYERS = {
    'default': {
    'BACKEND': 'channels_redis.core.RedisChannelLayer',
    'CONFIG': {"hosts": ["redis://10.211.55.25:6379/1"],},
    },
}
 

CHANNEL_LAYERS = {
    'default': {
    'BACKEND': 'channels_redis.core.RedisChannelLayer',
    'CONFIG': {"hosts": [('10.211.55.25', 6379)],},},
}
 

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": ["redis://:password@10.211.55.25:6379/0"],
            "symmetric_encryption_keys": [SECRET_KEY],
        },
    },
}
配置
from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync


class ChatConsumer(WebsocketConsumer):

    def connect(self):
        async_to_sync(self.channel_layer.group_add)('x1', self.channel_name)
        self.accept()

    def receive(self, text_data=None, bytes_data=None):
        async_to_sync(self.channel_layer.group_send)('x1', {
            'type': 'xxx.ooo',
            'message': text_data
        })

    def xxx_ooo(self, event):
        message = event['message']
        self.send(message)

    def disconnect(self, code):
        async_to_sync(self.channel_layer.group_discard)('x1', self.channel_name)
业务逻辑

 

posted @ 2020-08-26 02:28  silencio。  阅读(380)  评论(0编辑  收藏  举报