django
pip3 install channels==2.1.7
在seetings里注册 channels
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'channels', ]
ASGI_APPLICATION = "luffyapi.routing.application"
routing.py 文件
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),
])
})
====================================================================
consumers.py 文件
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
class ChatConsumer(WebsocketConsumer):
def websocket_connect(self, message):
self.accept()
self.send(text_data='收到了')
print(self.scope.get('query_string').decode('UTF-8','strict'))
def websocket_receive(self, message):
print('接收到消息')
print('接收到消息', message)
# self.send(text_data='收到了')
def websocket_disconnect(self, message):
print('客户端断开连接了')
raise StopConsumer()
前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<textarea class="form-control" id="chat-log" disabled rows="20"></textarea><br/>
<input class="form-control" id="chat-message-input" type="text"/><br/>
<input class="btn btn-success btn-block" id="chat-message-submit" type="button" onclick="send()" />
</body>
<script>
var chatSocket = new WebSocket('ws://127.0.0.1:8000/chat/?123')
function send(){
chatSocket.send('asdc')
}
</script>
</html>
=======================================================
基于 redis的channel layer
pip3 install channels
-
redis
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, AsyncWebsocketConsumer
from asgiref.sync import async_to_sync
import json
class AsyncConsumer(AsyncWebsocketConsumer):
async def connect(self): # 连接时触发
self.room_name = self.scope['url_route']['kwargs']['room_name'] # 获取地址栏的参数
self.room_group_name = 'notice_%s' % self.room_name # 直接从用户指定的房间名称构造Channels组名称,不进行任何引用或转义。
# 将新的连接加入到群组
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code): # 断开时触发
# 将关闭的连接从群组中移除
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
async def receive(self, text_data=None, bytes_data=None): # 接收消息时触发
text_data_json = json.loads(text_data)
message = text_data_json['message']
# 信息群发
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'system_message',
'message': message
}
)
# Receive message from room group
async def system_message(self, event):
print(event)
message = event['message']
# Send message to WebSocket单发消息
await self.send(text_data=json.dumps({
'message': message
}))
应用下创建 routing.py (类似Django路由)
apps/assets/routing.py
from django.conf.urls import url
from assets import consumers
websocket_urlpatterns = [
# url(r'^ws/msg/(?P<room_name>[^/]+)/$', consumers.SyncConsumer),
url(r'^ws/msg/(?P<room_name>[^/]+)/$', consumers.AsyncConsumer),
]
修改项目下 routing.py (主WS路由)
StarMeow/routing.py
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from channels.sessions import SessionMiddlewareStack
import assets.routing
application = ProtocolTypeRouter({
# (http->django views is added by default)
# 【channels】(第6步)添加路由配置指向应用的路由模块
'websocket': SessionMiddlewareStack( # 使用Session中间件,可以请求中session的值
URLRouter(
assets.routing.websocket_urlpatterns
)
),
})