django channels 是django支持websocket的一个模块。
1. 安装
1 | pip3 install channels |
2. 快速上手
2.1 在settings中添加配置
ASGI_APPLICATION = "django_channels_demo.routing.application"
2.2 创建websocket应用和路由
1 #!/usr/bin/env python 2 #-*- coding:utf-8 -*- 3 from channels.routing importProtocolTypeRouter, URLRouter 4 from django.conf.urls importurl 5 from chat importconsumers 6 7 8 application =ProtocolTypeRouter({ 9 'websocket': URLRouter([ 10 url(r'^chat/$', consumers.ChatConsumer), 11 ]) 12 })
2.3 编写处理websocket逻辑业务
1 #!/usr/bin/env python 2 #-*- coding:utf-8 -*- 3 from channels.generic.websocket importWebsocketConsumer 4 from channels.exceptions importStopConsumer 5 6 classChatConsumer(WebsocketConsumer): 7 8 defwebsocket_connect(self, message): 9 self.accept() 10 11 defwebsocket_receive(self, message): 12 print('接收到消息', message) 13 self.send(text_data='收到了') 14 15 defwebsocket_disconnect(self, message): 16 print('客户端断开连接了') 17 raise StopConsumer()
1 #!/usr/bin/env python 2 #-*- coding:utf-8 -*- 3 from channels.generic.websocket importWebsocketConsumer 4 from channels.exceptions importStopConsumer 5 6 7 classSimpleChatConsumer(WebsocketConsumer): 8 defconnect(self): 9 self.accept() 10 11 def receive(self, text_data=None, bytes_data=None): 12 self.send(text_data) 13 14 #主动断开连接 15 #self.close() 16 17 defdisconnect(self, code): 18 print('客户端要断开了') 19 20 示例二
1 #!/usr/bin/env python 2 #-*- coding:utf-8 -*- 3 from channels.generic.websocket importWebsocketConsumer 4 from channels.exceptions importStopConsumer 5 6 7 CLIENTS =[] 8 9 classChatConsumer(WebsocketConsumer): 10 11 defconnect(self): 12 self.accept() 13 CLIENTS.append(self) 14 15 def receive(self, text_data=None, bytes_data=None): 16 for item inCLIENTS: 17 item.send(text_data) 18 19 #主动断开连接 20 #self.close() 21 22 defdisconnect(self, code): 23 CLIENTS.remove(self) 24 25 示例三
3. channel layer
基于内存的channel layer
1 CHANNEL_LAYERS ={ 2 "default": { 3 "BACKEND": "channels.layers.InMemoryChannelLayer", 4 } 5 }
1 from channels.generic.websocket importWebsocketConsumer 2 from asgiref.sync importasync_to_sync 3 4 5 classChatConsumer(WebsocketConsumer): 6 7 defconnect(self): 8 async_to_sync(self.channel_layer.group_add)('x1', self.channel_name) 9 self.accept() 10 11 def receive(self, text_data=None, bytes_data=None): 12 async_to_sync(self.channel_layer.group_send)('x1', { 13 'type': 'xxx.ooo', 14 'message': text_data 15 }) 16 17 defxxx_ooo(self, event): 18 message = event['message'] 19 self.send(message) 20 21 defdisconnect(self, code): 22 async_to_sync(self.channel_layer.group_discard)('x1', self.channel_name) 23 24 业务处理
基于 redis的channel layer
pip3 install channels
-
redis
1 CHANNEL_LAYERS ={ 2 "default": { 3 "BACKEND": "channels_redis.core.RedisChannelLayer", 4 "CONFIG": { 5 "hosts": [('10.211.55.25', 6379)] 6 }, 7 }, 8 } 9 10 11 CHANNEL_LAYERS ={ 12 'default': { 13 'BACKEND': 'channels_redis.core.RedisChannelLayer', 14 'CONFIG': {"hosts": ["redis://10.211.55.25:6379/1"],}, 15 }, 16 } 17 18 19 CHANNEL_LAYERS ={ 20 'default': { 21 'BACKEND': 'channels_redis.core.RedisChannelLayer', 22 'CONFIG': {"hosts": [('10.211.55.25', 6379)],},}, 23 } 24 25 26 CHANNEL_LAYERS ={ 27 "default": { 28 "BACKEND": "channels_redis.core.RedisChannelLayer", 29 "CONFIG": { 30 "hosts": ["redis://:password@10.211.55.25:6379/0"], 31 "symmetric_encryption_keys": [SECRET_KEY], 32 }, 33 }, 34 } 35 36 配置
1 from channels.generic.websocket importWebsocketConsumer 2 from asgiref.sync importasync_to_sync 3 4 5 classChatConsumer(WebsocketConsumer): 6 7 defconnect(self): 8 async_to_sync(self.channel_layer.group_add)('x1', self.channel_name) 9 self.accept() 10 11 def receive(self, text_data=None, bytes_data=None): 12 async_to_sync(self.channel_layer.group_send)('x1', { 13 'type': 'xxx.ooo', 14 'message': text_data 15 }) 16 17 defxxx_ooo(self, event): 18 message = event['message'] 19 self.send(message) 20 21 defdisconnect(self, code): 22 async_to_sync(self.channel_layer.group_discard)('x1', self.channel_name) 23 24 业务逻辑