zoukankan      html  css  js  c++  java
  • 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)
    业务逻辑
  • 相关阅读:
    Java读取Excel文件(包括xls和xlsx)的样例程序
    Node.js中使用pipe拷贝大文件不能完全拷贝的解决办法
    Spring Boot中一个Servlet主动断开连接的方法
    算法学习笔记1.3.3 质因数分解
    算法学习笔记1.3.2 素数判定
    算法学习笔记1.3.1 素数筛法
    算法学习笔记1.2.2 扩展欧几里得
    算法学习笔记1.2.1 欧几里得算法
    算法学习笔记1.1.3 矩阵的逆
    Windows下Tesseract-OCR的安装
  • 原文地址:https://www.cnblogs.com/bubu99/p/13562911.html
Copyright © 2011-2022 走看看