其他的配置不赘述了,直接网上搜一下django使用channel的配置方法
我初步研究通道先用的内存
在setting文件中
python
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels.layers.InMemoryChannelLayer",
},
}
这里我重点说一下luckysheet源码的部分
首先是websocket,这部分代码在源码的server.js中,通过研究源码,才解决了问题
pako解压的问题尝试了很多次都没不太对,于是直接把pako部分的源码给注释掉了,直接传过去的就是json字符串
javascript
} else {
// let msg = pako.gzip(encodeURIComponent(JSON.stringify(d)), {to: "string"});
let msg = JSON.stringify(d);
//console.info(msg);
if (_this.websocket != null) {
_this.websocket.send(msg);
}
}
后端的消费者类的主要代码如下
python
from channels.generic.websocket import AsyncJsonWebsocketConsumer
from urllib.parse import parse_qs
import json
class TableConsumer(AsyncJsonWebsocketConsumer):
table = None
gridKey = None
async def connect(self):
query = self.scope['query_string'].decode('utf-8')
t = parse_qs(query)['t'][0]
self.gridKey = parse_qs(query)['g'][0]
await self.channel_layer.group_add(f'table_{self.gridKey}', self.channel_name)
await self.accept()
print('建立连接')
async def disconnect(self, close_code):
print('断开连接')
await self.channel_layer.group_discard(f'table_{self.gridKey}', self.channel_name)
async def receive(self, text_data=None, bytes_data=None):
# 使用json.loads方法将JSON字符串解析为Python的字典对象
if text_data !='rub':
parsed_data = json.loads(text_data)
print(parsed_data)
# 这里构造要广播的数据
broadcast_data = dict()
broadcast_data['type'] = 3
broadcast_data['data'] = text_data
broadcast_data['username'] = 'test'
broadcast_event = {
"type": "broadcast_message",
"message": broadcast_data
}
# 向对应的组发送广播事件,触发broadcast_message方法来实际发送给组内成员
await self.channel_layer.group_send(f'table_{self.gridKey}', broadcast_event)
async def broadcast_message(self, event):
message = event["message"]
await self.send_json(message)
之前对websocket和channel不太了解,看了前端代码后把type和message给改了,后来多次尝试发现这个千万别改,他会在send的时候卡住而且不报任何错误(因为协程),如果是广播的话只需要修改broadcast_data的内容就行,通过解读前端的代码,在后端构建返回的json,成果把type=3的内容实现了,也就是鼠标移动的部分
javascript
else if(type == 3){ //多人操作不同选区("t": "mv")(用不同颜色显示其他人所操作的选区)
let id = data.id;
let username = data.username;
let item = JSON.parse(data.data);
let type = item.t,
index = item.i,
value = item.v;
剩余的部分我就先不写了,具体操作应该是根据前端过来的json内容来自行判断返回的type,然后进行消息的分发!!!!
重点:读源码读源码读源码!!!!!
又写了两种type,批量的没写到type=4的情况,因为他前端写的感觉有问题还造成了后端的麻烦,于是后端写成多个type=2了,增加了一点点服务器压力
python
from channels.generic.websocket import AsyncJsonWebsocketConsumer
from urllib.parse import parse_qs
import json
from pyasn1_modules.rfc5639 import brainpoolP160r1
class TableConsumer(AsyncJsonWebsocketConsumer):
table = None
gridKey = None
async def connect(self):
query = self.scope['query_string'].decode('utf-8')
t = parse_qs(query)['t'][0]
self.gridKey = parse_qs(query)['g'][0]
await self.channel_layer.group_add(f'table_{self.gridKey}', self.channel_name)
await self.accept()
print('建立连接')
async def disconnect(self, close_code):
print('断开连接')
await self.channel_layer.group_discard(f'table_{self.gridKey}', self.channel_name)
async def receive(self, text_data=None, bytes_data=None):
# 使用json.loads方法将JSON字符串解析为Python的字典对象
if text_data !='rub':
parsed_data = json.loads(text_data)
print(parsed_data)
if parsed_data['t'] == 'mv':
# 这里构造要广播的事件数据,假设要原封不动广播接收到的数据,将其放入'message'字段
broadcast_data = dict()
broadcast_data['type'] = 3
broadcast_data['data'] = text_data
broadcast_data['username'] = 'test'
broadcast_event = {
"type": "broadcast_message",
"message": broadcast_data
}
# 向对应的组发送广播事件,触发broadcast_message方法来实际发送给组内成员
await self.channel_layer.group_send(f'table_{self.gridKey}', broadcast_event)
if parsed_data['t'] == 'v':
# 这里构造要广播的事件数据,假设要原封不动广播接收到的数据,将其放入'message'字段
broadcast_data = dict()
broadcast_data['type'] = 2
broadcast_data['data'] = text_data
broadcast_data['username'] = 'test'
broadcast_event = {
"type": "broadcast_message",
"message": broadcast_data
}
# 向对应的组发送广播事件,触发broadcast_message方法来实际发送给组内成员
await self.channel_layer.group_send(f'table_{self.gridKey}', broadcast_event)
if parsed_data['t'] == 'rv':
row = parsed_data['range']['row']
column = parsed_data['range']['column']
for j in range(column[0], column[1]+1):
numj = j-column[0]
for i in range(row[0], row[1] + 1):
numi = i-row[0]
try:
broadcast_data = dict()
broadcast_data['type'] = 2
# data = list()
broadcast_data['username'] = 'test'
data = dict()
data['t'] = 'v'
data['i'] = 0
data['v'] = parsed_data['v'][numi][numj]
data['r'] = i
data['c'] = j
broadcast_data['data'] = json.dumps(data)
broadcast_event = {
"type": "broadcast_message",
"message": broadcast_data
}
await self.channel_layer.group_send(f'table_{self.gridKey}', broadcast_event)
except Exception as e:
print(e)
async def broadcast_message(self, event):
message = event["message"]
await self.send_json(message)