思路
- channels 提供了在Consumer外部調用發送信息的方式,channels中每個客戶端連接時會生成一個channel_name, 而channel_name對應了是哪個客戶端, group_name對應的是用戶組。
- 那麼可以通過把channel_name和group_name的值保存下來,在http請求的接口中進行外部調用。
實例
例子是繼承AsyncJsonWebsocketConsumer
的, 所以是異步的,可接受發送json
格式的數據, 代碼如下。
from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncJsonWebsocketConsumer
@database_sync_to_async
def save_channel_name(key, channel_name, group_name):
"""
:param key:
:param channel_name:
:param group_name:
:return:
"""
# 這裏可以通過redis或數據庫將對於的channel_name, group_name保存下來。
pass
class WbConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
# 這
key = self.scope['url_route']['kwargs']['peronId'] # 在websocket鏈接的時候獲取到用戶標識,可以從jwt信息中獲取,可以在路由中獲取某個參數作爲標識
group_name = 'group_' + key
await save_channel_name(key, self.channel_name)
# 當前頻道添加進頻道組
await self.channel_layer.group_add(group_name, self.channel_name)
await self.accept()
async def disconnect(self, code):
print('關閉連接')
async def receive_json(self, content, **kwargs):
print('接收數據:', content)
await self.send_json(content={
'msg': '收到收到over!'
})
async def test_message(self, event):
"""
發送測試數據
:param event:
:return:
"""
message = event['message']
await self.send_json(message)
首先在connect
方法中, 可以拿到客戶端發起連接的請求路由參數,請求頭等,如使用jwt
認證的話,解析header
裏面的信息可以拿到用戶ID, 以用戶ID作爲鍵將channel_name
和group_name
保存起來。
- http發起請求的接口中,可以定義:
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
channel_layer = get_channel_layer()
channel_name = 'xxxx' # 獲取到之前保存的對應的channel_name
group_name = 'xxxxx' # 獲取到之前保存的對應的group_name
# 同步發送數據到組
async_to_sync(channel_layer.group_send)(group_name, {"type": "test.message"})
# 同步方式發送數據到對應websocket連接
async_to_sync(channel_layer.send)(channel_name, {"type": "test.message"})