功能变化: 重构websocket
parent
1bd16a722e
commit
90e47bdee5
|
@ -18,10 +18,10 @@ from application.websocketConfig import websocket_application
|
|||
|
||||
http_application = get_asgi_application()
|
||||
|
||||
async def application(scope,receive,send):
|
||||
if scope['type'] == 'http':
|
||||
await http_application(scope, receive, send)
|
||||
elif scope['type'] == 'websocket':
|
||||
await websocket_application(scope, receive, send)
|
||||
else:
|
||||
raise Exception("未知的scope类型,"+ scope['type'])
|
||||
# async def application(scope,receive,send):
|
||||
# if scope['type'] == 'http':
|
||||
# await http_application(scope, receive, send)
|
||||
# elif scope['type'] == 'websocket':
|
||||
# await websocket_application(scope, receive, send)
|
||||
# else:
|
||||
# raise Exception("未知的scope类型,"+ scope['type'])
|
|
@ -1,13 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from channels.auth import AuthMiddlewareStack
|
||||
from channels.routing import ProtocolTypeRouter, URLRouter
|
||||
from dvadmin.system import routing as dvadminRouting
|
||||
|
||||
from django.urls import path
|
||||
|
||||
from application.websocketConfig import MegCenter
|
||||
|
||||
websocket_urlpatterns = [
|
||||
path('ws/<str:service_uid>/', MegCenter.as_asgi()), #consumers.DvadminWebSocket 是该路由的消费者
|
||||
]
|
||||
|
||||
application = ProtocolTypeRouter({
|
||||
'websocket': AuthMiddlewareStack(
|
||||
URLRouter(
|
||||
dvadminRouting.websocket_urlpatterns# 指明路由文件是devops/routing.py
|
||||
websocket_urlpatterns #指明路由文件是devops/routing.py
|
||||
)
|
||||
),
|
||||
})
|
|
@ -1,114 +1,100 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import django
|
||||
|
||||
django.setup()
|
||||
import json
|
||||
import urllib
|
||||
|
||||
#处理websocket传参
|
||||
from asgiref.sync import sync_to_async, async_to_sync
|
||||
from channels.db import database_sync_to_async
|
||||
from channels.generic.websocket import AsyncJsonWebsocketConsumer, AsyncWebsocketConsumer
|
||||
import json
|
||||
|
||||
from channels.layers import get_channel_layer
|
||||
from jwt import InvalidSignatureError
|
||||
|
||||
from application import settings
|
||||
from dvadmin.system.models import MessageCenter
|
||||
|
||||
send_dict = {}
|
||||
|
||||
# 发送消息结构体
|
||||
def message(sender, msg_type, msg):
|
||||
text = {
|
||||
'sender': sender,
|
||||
'contentType': msg_type,
|
||||
'content': msg,
|
||||
}
|
||||
return text
|
||||
|
||||
#异步获取消息中心的目标用户
|
||||
@database_sync_to_async
|
||||
def _get_message_center_instance(message_id):
|
||||
_MessageCenter = MessageCenter.objects.filter(id=message_id).values_list('target_user',flat=True)
|
||||
if _MessageCenter:
|
||||
return _MessageCenter
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
def request_data(scope):
|
||||
query_string = scope.get('query_string', b'').decode('utf-8')
|
||||
qs = urllib.parse.parse_qs(query_string)
|
||||
return qs
|
||||
|
||||
|
||||
# 全部的websocket sender
|
||||
CONNECTIONS = {}
|
||||
class DvadminWebSocket(AsyncJsonWebsocketConsumer):
|
||||
async def connect(self):
|
||||
try:
|
||||
import jwt
|
||||
self.service_uid = self.scope["url_route"]["kwargs"]["service_uid"]
|
||||
decoded_result = jwt.decode(self.service_uid, settings.SECRET_KEY, algorithms=["HS256"])
|
||||
if decoded_result:
|
||||
self.user_id = decoded_result.get('user_id')
|
||||
self.chat_group_name = "user_"+str(self.user_id)
|
||||
#收到连接时候处理,
|
||||
await self.channel_layer.group_add(
|
||||
self.chat_group_name,
|
||||
self.channel_name
|
||||
)
|
||||
await self.accept()
|
||||
await self.send_json(message('system', 'SYSTEM', '连接成功'))
|
||||
except InvalidSignatureError:
|
||||
await self.disconnect(None)
|
||||
|
||||
|
||||
# 判断用户是否已经连接
|
||||
def check_connection(key):
|
||||
return key in CONNECTIONS
|
||||
async def disconnect(self, close_code):
|
||||
# Leave room group
|
||||
await self.channel_layer.group_discard(self.chat_group_name, self.channel_name)
|
||||
print("连接关闭")
|
||||
await self.close(close_code)
|
||||
|
||||
|
||||
# 发送消息结构体
|
||||
def message(sender, msg_type, msg):
|
||||
text = json.dumps({
|
||||
'sender': sender,
|
||||
'contentType': msg_type,
|
||||
'content': msg,
|
||||
})
|
||||
return {
|
||||
'type': 'websocket.send',
|
||||
'text': text
|
||||
class MegCenter(DvadminWebSocket):
|
||||
"""
|
||||
消息中心
|
||||
"""
|
||||
|
||||
async def receive(self, text_data):
|
||||
# 接受客户端的信息,你处理的函数
|
||||
text_data_json = json.loads(text_data)
|
||||
message_id = text_data_json.get('message_id', None)
|
||||
user_list = await _get_message_center_instance(message_id)
|
||||
for send_user in user_list:
|
||||
await self.channel_layer.group_send(
|
||||
"user_" + str(send_user),
|
||||
{'type': 'push.message', 'message': text_data_json}
|
||||
)
|
||||
|
||||
async def push_message(self, event):
|
||||
message = event['message']
|
||||
await self.send(text_data=json.dumps(message))
|
||||
|
||||
|
||||
def push(username, event):
|
||||
"""
|
||||
主动推送消息
|
||||
"""
|
||||
channel_layer = get_channel_layer()
|
||||
async_to_sync(channel_layer.group_send)(
|
||||
username,
|
||||
{
|
||||
"type": "push.message",
|
||||
"event": event
|
||||
}
|
||||
|
||||
|
||||
async def websocket_application(scope, receive, send):
|
||||
while True:
|
||||
event = await receive()
|
||||
# print('[event] ', event)
|
||||
qs = request_data(scope)
|
||||
print(1,qs)
|
||||
auth = qs.get('auth', [''])[0]
|
||||
user_id = None
|
||||
# 收到建立WebSocket连接的消息
|
||||
if event['type'] == 'websocket.connect':
|
||||
# 昵称验证
|
||||
if not auth:
|
||||
break
|
||||
else:
|
||||
try:
|
||||
import jwt
|
||||
decoded_result = jwt.decode(auth, settings.SECRET_KEY, algorithms=["HS256"])
|
||||
if decoded_result:
|
||||
user_id = decoded_result.get('user_id')
|
||||
# 记录
|
||||
CONNECTIONS[user_id] = send
|
||||
except InvalidSignatureError:
|
||||
break
|
||||
if auth in CONNECTIONS:
|
||||
break
|
||||
|
||||
await send({'type': 'websocket.accept'})
|
||||
await send(message('system', 'INFO', '连接成功'))
|
||||
# # 发送好友列表
|
||||
# friends_list = list(CONNECTIONS.keys())
|
||||
# await send(message('system', 'INFO', friends_list))
|
||||
#
|
||||
# # 向其他人群发消息, 有人登录了
|
||||
# for other in CONNECTIONS.values():
|
||||
# await other(message('system', 'addFriend', auth))
|
||||
|
||||
|
||||
# 收到中断WebSocket连接的消息
|
||||
elif event['type'] == 'websocket.disconnect':
|
||||
# 移除记录
|
||||
if user_id in CONNECTIONS:
|
||||
CONNECTIONS.pop(user_id)
|
||||
|
||||
# # 向其他人群发消息, 有人离线了
|
||||
# for other in CONNECTIONS.values():
|
||||
# await other(message('system', 'removeFriend', user_id))
|
||||
|
||||
# 其他情况,正常的WebSocket消息
|
||||
elif event['type'] == 'websocket.receive':
|
||||
|
||||
if event['text'] == 'ping':
|
||||
await send(message('system', 'text', 'pong!'))
|
||||
else:
|
||||
receive_msg = json.loads(event['text'])
|
||||
message_id = receive_msg.get('message_id', None)
|
||||
_MessageCenter = MessageCenter.objects.filter(id=message_id).first()
|
||||
if _MessageCenter:
|
||||
user_list = _MessageCenter.target_user.values_list('id',flat=True)
|
||||
for send_user in user_list:
|
||||
if send_user in CONNECTIONS:
|
||||
content_type = receive_msg.get('contentType', 'TEXT')
|
||||
content = receive_msg.get('content', '')
|
||||
msg = message(user_id, content_type, content)
|
||||
await CONNECTIONS[send_user](msg)
|
||||
else:
|
||||
msg = message('system', 'text', '对方已下线或不存在')
|
||||
await send(msg)
|
||||
else:
|
||||
print('a1a1a1')
|
||||
pass
|
||||
|
||||
print('[disconnect]')
|
||||
)
|
|
@ -1,95 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import urllib
|
||||
|
||||
from asgiref.sync import sync_to_async
|
||||
from channels.db import database_sync_to_async
|
||||
from channels.generic.websocket import AsyncJsonWebsocketConsumer, AsyncWebsocketConsumer
|
||||
import json
|
||||
|
||||
from jwt import InvalidSignatureError
|
||||
|
||||
from application import settings
|
||||
from dvadmin.system.models import MessageCenter
|
||||
|
||||
send_dict = {}
|
||||
|
||||
# 发送消息结构体
|
||||
def message(sender, msg_type, msg):
|
||||
text = {
|
||||
'sender': sender,
|
||||
'contentType': msg_type,
|
||||
'content': msg,
|
||||
}
|
||||
return text
|
||||
|
||||
#异步获取消息中心的目标用户
|
||||
@database_sync_to_async
|
||||
def _get_message_center_instance(message_id):
|
||||
_MessageCenter = MessageCenter.objects.filter(id=message_id).values_list('target_user',flat=True)
|
||||
if _MessageCenter:
|
||||
return _MessageCenter
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
def request_data(scope):
|
||||
query_string = scope.get('query_string', b'').decode('utf-8')
|
||||
qs = urllib.parse.parse_qs(query_string)
|
||||
return qs
|
||||
|
||||
class DvadminWebSocket(AsyncJsonWebsocketConsumer):
|
||||
async def connect(self):
|
||||
try:
|
||||
import jwt
|
||||
self.service_uid = self.scope["url_route"]["kwargs"]["service_uid"]
|
||||
params = request_data(self.scope)
|
||||
room = params.get('room')[0]
|
||||
decoded_result = jwt.decode(self.service_uid, settings.SECRET_KEY, algorithms=["HS256"])
|
||||
if decoded_result:
|
||||
self.user_id = decoded_result.get('user_id')
|
||||
self.chat_group_name = room
|
||||
#收到连接时候处理,
|
||||
await self.channel_layer.group_add(
|
||||
self.chat_group_name,
|
||||
self.channel_name
|
||||
)
|
||||
# 将该客户端的信息发送函数与客户端的唯一身份标识绑定,保存至自定义的字典中
|
||||
if len(send_dict)==0:
|
||||
send_dict.setdefault(self.chat_group_name, {})
|
||||
for room in send_dict.keys():
|
||||
if room == self.chat_group_name:
|
||||
send_dict[self.chat_group_name][self.user_id] = self.send
|
||||
else:
|
||||
send_dict.setdefault(self.chat_group_name,{})
|
||||
await self.accept()
|
||||
await self.send_json(message('system', 'SYSTEM', '连接成功'))
|
||||
except InvalidSignatureError:
|
||||
await self.disconnect(None)
|
||||
|
||||
|
||||
async def disconnect(self, close_code):
|
||||
# 删除 send_dict 中对应的信息
|
||||
del send_dict[self.chat_group_name][self.user_id]
|
||||
# Leave room group
|
||||
await self.channel_layer.group_discard(self.chat_group_name, self.channel_name)
|
||||
print("连接关闭")
|
||||
await self.close(close_code)
|
||||
|
||||
|
||||
class MegCenter(DvadminWebSocket):
|
||||
"""
|
||||
消息中心
|
||||
"""
|
||||
async def receive(self, text_data=None, byte_text_data=None):
|
||||
print(text_data)
|
||||
try:
|
||||
text_data_json = json.loads(text_data)
|
||||
except Exception as e:
|
||||
print('数据无法被json格式化', e)
|
||||
await self.disconnect(400)
|
||||
else:
|
||||
# 获取将要推送信息的目标身份标识,调用保存在 send_dict中的信息发送函数
|
||||
message_id = text_data_json.get('message_id', None)
|
||||
user_list = await _get_message_center_instance(message_id)
|
||||
for send_user in user_list:
|
||||
await send_dict[self.chat_group_name][send_user](text_data=json.dumps(text_data_json))
|
|
@ -1,7 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from django.urls import path
|
||||
from . import consumers
|
||||
|
||||
websocket_urlpatterns = [
|
||||
path('ws/<str:service_uid>/', consumers.MegCenter.as_asgi()), #consumers.DvadminWebSocket 是该路由的消费者
|
||||
]
|
|
@ -1,6 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from itertools import chain
|
||||
|
||||
import json
|
||||
from django_restql.fields import DynamicSerializerMethodField
|
||||
from rest_framework import serializers
|
||||
from rest_framework.decorators import action, permission_classes
|
||||
|
@ -181,7 +180,6 @@ class MessageCenterViewSet(CustomModelViewSet):
|
|||
self_user_id = self.request.user.id
|
||||
queryset = MessageCenterTargetUser.objects.filter(users__id=self_user_id).exclude(
|
||||
messagecenter__is_deleted=True).order_by('create_datetime').last()
|
||||
print(queryset)
|
||||
data = None
|
||||
if queryset:
|
||||
serializer = MessageCenterTargetUserListSerializer(queryset, many=False, request=request)
|
||||
|
|
|
@ -3,7 +3,7 @@ import util from '@/libs/util'
|
|||
function initWebSocket (e) {
|
||||
const token = util.cookies.get('token')
|
||||
if (token) {
|
||||
const wsUri = process.env.VUE_APP_WEBSOCKET + '/ws/' + token + '/?room=message_center'
|
||||
const wsUri = process.env.VUE_APP_WEBSOCKET + '/ws/' + token + '/'
|
||||
this.socket = new WebSocket(wsUri)// 这里面的this都指向vue
|
||||
this.socket.onerror = webSocketOnError
|
||||
this.socket.onmessage = webSocketOnMessage
|
||||
|
@ -20,6 +20,12 @@ function webSocketOnError (e) {
|
|||
duration: 3000
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收消息
|
||||
* @param e
|
||||
* @returns {any}
|
||||
*/
|
||||
function webSocketOnMessage (e) {
|
||||
const data = JSON.parse(e.data)
|
||||
if (data.contentType === 'SYSTEM') {
|
||||
|
@ -58,9 +64,13 @@ function closeWebsocket () {
|
|||
this.socket.close()
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
* @param message
|
||||
*/
|
||||
function webSocketSend (message) {
|
||||
this.socket.send(JSON.stringify(message))
|
||||
}
|
||||
export default {
|
||||
initWebSocket, closeWebsocket, webSocketSend
|
||||
initWebSocket, closeWebsocket, webSocketSend,webSocketOnMessage
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue