赞
踩
channels 4.0之后默认不带Daphne服务器了。
解决方案可以有两种:
1.指定channels的版本为3.x;
2.安装时使用pip3 install -U channels[“daphne”]
pip3 install channels==3.0.3 -i https://pypi.douban.com/simple
- INSTALLED_APPS = [
- 'channels',
- ]
- ASGI_APPLICATION = "qq_chart.asgi.application"
- ASGI_APPLICATION = '当前项目名同名的文件名.asgi.application'
- import os
- from django.core.asgi import get_asgi_application
- from channels.routing import ProtocolTypeRouter, URLRouter
- from . import routings
- os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'qq_chart.settings')
-
- # application = get_asgi_application()
- application = ProtocolTypeRouter({
- 'http':get_asgi_application(),
- 'websocket':URLRouter(routings.websocket_urlpatterns)
- })
- from django.urls import re_path
- from app01 import consumers
-
- websocket_urlpatterns = [
- re_path(r'ws/(?P<group>\w+)/$', consumers.ChatConsumer.as_asgi())
- ]
- from channels.exceptions import StopConsumer
- from channels.generic.websocket import WebsocketConsumer
- # 异步改成同步
- from asgiref.sync import async_to_sync
-
-
- class ChatConsumer(WebsocketConsumer):
- def websocket_connect(self, message):
- '''客户端请求建立链接时 自动触发'''
- self.accept() # 建立链接 并且自动帮你维护每一个客户端
-
- def websocket_receive(self, message):
- '''客户端发送数据过来 自动触发'''
- print(message)
- self.send('小心电信诈骗')
-
- def websocket_disconnect(self, message):
- '''客户端断开链接之后 自动触发'''
- print('断开链接')
- raise StopConsumer()

这里放入内存中,也可以选择放入redis中
pip3 install channels_redis# settings.py
# 群聊配置# 无密码1
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [('IP', 6379)]
},
},
}# 无密码2 选择使用的库
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {"hosts": ["redis://IP:6379/1"],},
},
}# 有密码
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": ["redis://:password@IP:6379/0"],
# SECRET_KEY settings内置的
"symmetric_encryption_keys": [SECRET_KEY],
},
},
}
- # 群聊配置
- CHANNEL_LAYERS = {
- "default": {
- "BACKEND": "channels.layers.InMemoryChannelLayer",
- }
- }
- """
- websocket逻辑
- """
- from channels.generic.websocket import WebsocketConsumer
- from channels.exceptions import StopConsumer
- from asgiref.sync import async_to_sync
-
-
- class ChatConsumer(WebsocketConsumer):
- # 有客户端来向后端发送websocket连接的请求,自动触发
- def websocket_connect(self, message):
- # 允许创建链接
- self.accept()
- print('有人来连接了')
- # 不允许连接
- # raise StopConsumer()
-
- # 服务端与客户端发送消息
- # self.send(text_data='你好')
-
- # 群聊的配置
- # 将客户端的连接对象加入内存/redis
- # 1999群号,这个过程是异步的,要修改成同步的
- # self.channel_name当前用户
- group = self.scope['url_route']['kwargs'].get('group')
- async_to_sync(self.channel_layer.group_add)(group, self.channel_name)
-
- # 浏览器基于websocket向后端发送数据,自动触发
- def websocket_receive(self, message):
- print('接收到消息----》', message)
- text = message.get('text')
- if text == 'close':
- # 服务端主动断开
- self.close()
- # 可以让websocket_disconnect函数不执行
- raise StopConsumer()
- # 给一个人回复
- # self.send(text_data='收到了')
- # 群聊
- # 通知组内的所有客户端,去执行xx_oo的方法,
- group = self.scope['url_route']['kwargs'].get('group')
-
- async_to_sync(self.channel_layer.group_send)(group, {'type': 'xx.oo', 'message': message})
-
- def xx_oo(self, event):
- """
- 群聊
- :return:
- """
- print('--------->', event['message'])
- text = event['message']['text']
- # 给所有人回复
- self.send(text)
-
- # 当客户端/服务端主动断开连接自动触发
- def websocket_disconnect(self, message):
- group = self.scope['url_route']['kwargs'].get('group')
-
- print('客户端主动断开连接了')
- # 可以让websocket_disconnect函数不执行
- # 群聊断开
- async_to_sync(self.channel_layer.group_discard)(group, self.channel_name) # self.channel_name当前名字
- raise StopConsumer()

- """
- websocket逻辑
- """
- import json
- from channels.generic.websocket import WebsocketConsumer
- from channels.exceptions import StopConsumer
- from asgiref.sync import async_to_sync
- from chart import models
-
-
- class ChatConsumer(WebsocketConsumer):
- # 有客户端来向后端发送websocket连接的请求,自动触发
- def websocket_connect(self, message):
- # 允许创建链接
- self.accept()
- print('有人来连接了-----群聊')
- # 不允许连接
- # raise StopConsumer()
-
- # 服务端与客户端发送消息
- # self.send(text_data='你好')
-
- # 群聊的配置
- # 将客户端的连接对象加入内存/redis
- # 1999群号,这个过程是异步的,要修改成同步的
- # self.channel_name当前用户
- group = self.scope['url_route']['kwargs'].get('group')
- username = self.scope['url_route']['kwargs'].get('username')
-
- query = models.Chart_Record_all.objects.filter(chart_num=group, is_delete=False, is_active=True)
- for item in query:
- if item.username:
- # print('发言人:', item.username)
- self.send(
- json.dumps(
- {'username': item.username.username, 'text': item.text, 'timer': str(item.create_time)[0:19]},
- ensure_ascii=False))
- async_to_sync(self.channel_layer.group_add)(group, self.channel_name)
- # 获取当前组的发言记录
-
- # 浏览器基于websocket向后端发送数据,自动触发
- def websocket_receive(self, message):
- print('接收到消息----》', message)
- text = message.get('text')
- print(text)
- # 给一个人回复
- # self.send(text_data='收到了')
- # 群聊
- # 通知组内的所有客户端,去执行xx_oo的方法,
- # group = self.scope['url_route']['kwargs'].get('group')
- group = self.scope['url_route']['kwargs'].get('group')
- username = self.scope['url_route']['kwargs'].get('username')
- obj = models.UserInfo.objects.get(username=username)
- # text = event['message']['text']
- chart_obj = models.Chart_Record_all.objects.create(chart_num=group, username=obj, text=text)
- async_to_sync(self.channel_layer.group_send)(group,
- # type:触发的函数名称
- {'type': 'chart.room',
- 'message': {'message': message, 'chart_obj': chart_obj}})
-
- def chart_room(self, event):
- """
- 群聊
- :return:
- """
- # print('--------->', event['message'])
- # 获取组号及发言人
- # group = self.scope['url_route']['kwargs'].get('group')
- # username = self.scope['url_route']['kwargs'].get('username')
- # obj = models.UserInfo.objects.get(username=username)
- # text = event['message']['text']
- # chart_obj = models.Chart_Record_all.objects.create(chart_num=group, username=obj, text=text)
- chart_obj = event['message']['chart_obj']
- if chart_obj.username:
- # 给所有人回复
- self.send(
- json.dumps(
- {'username': chart_obj.username.username, 'text': chart_obj.text,
- 'timer': str(chart_obj.create_time)[0:19]},
- ensure_ascii=False))
-
- # 当客户端/服务端主动断开连接自动触发
- def websocket_disconnect(self, message):
- group = self.scope['url_route']['kwargs'].get('group')
-
- print('客户端主动断开连接了')
- # 可以让websocket_disconnect函数不执行
- # 群聊断开
- async_to_sync(self.channel_layer.group_discard)(group, self.channel_name) # self.channel_name当前名字
- raise StopConsumer()

- <script>
-
- socket = new WebSocket("ws://127.0.0.1:8000/all_chart/{{ room_id }}/{{ username }}/")
- // 1.发送数据
- $("#send").click(function () {
- let mess = $('#txt').val()
- socket.send(mess)
- $('#txt').val('')
- })
-
-
- // 2.接收服务端返回的数据
- socket.onmessage = function (event) {
- {#console.log(event.data)#}
- var data = JSON.parse(event.data)
- // event.data 返回的数据
- // 创建标签
- var cn_div = $("<div>").attr('class', 'conversation-name')
-
- var mb_p = $("<p>").attr('class', 'mb-0').text(data.text)
- var ctec_div = $("<div>").attr('class', 'ctext-wrap-content').append(mb_p)
- var cte_div = $("<div>").attr('class', 'ctext-wrap').append(ctec_div)
- var user_div = $("<div>").attr('class', 'user-chat-content').append(cte_div).append(data.username + ' ' + '发言时间:' + data.timer)
-
- var con_div = $("<div>").attr('class', 'conversation-list').append(user_div)
-
-
- var li = $("<li>").append(con_div)
- // 获取ul
- $("#old_ul").append(li)
-
- //添加文本数据到标签里面
-
- }
- //3 客户端连接服务端成功之后自动触发 self.accept()成功之后
- socket.onopen = function (event) {
- {#// 创建标签#}
- {#var link = $("<div>")#}
- {#// 获取message#}
- {#let message = $("#message")#}
- {#link.html("连接成功")#}
- {##}
- {#//添加文本数据到标签里面#}
- {#message.append(link)#}
- }
- </script>

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。