django channels
django channels 是django支持websocket的一个模块。
1. 安装
pip3 install channels
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', ]
ASGI_APPLICATION = "django_channels_demo.routing.application"
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)