[英]Django Channels can't "socket.send" when trying to constantly send data to client from server
[英]How to send event to client from any place of server using django channels and websockets
現在我正在使用 django 和 angular 構建網站,並且我想在客戶端和服務器之間添加 websocket 通信。 我按照 django 頻道文檔的說明進行操作。( https://channels.readthedocs.io/ )我想從 django 服務器代碼的任何位置發送任何事件。 但是當多個用戶通過套接字連接時,服務器發送的數據總是發送到最后一個連接的用戶。 這就是我所做的。 首先在consumers.py中,我定義了我的ChatConsumer class,並添加了一個名為“tweet_send”的新處理程序function
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.room_name
# Join room group
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
...
# here's what I added a new tweet send handler
async def tweet_send(self, event):
content = event['content']
content["group_name"] = self.room_group_name
# Send message to WebSocket
await self.send(text_data=json.dumps({
"type": "MESSAGE",
"data": content
}))
在 django 服務器端(在 serializers.py 中)的某處,當創建新推文時,我使用 django.channel_layer 向所有用戶發送新推文數據
...
def create(self, validated_data):
...
new_tweet.save()
# send message via channels
channel_layer = get_channel_layer()
all_users = list(Member.objects.filter(is_active = True).values_list('id', flat = True))
for user_id in all_users:
async_to_sync(channel_layer.group_send)(
"chat_{}".format(user_id), # this is the group name of group name of individual users.
{ "type": "chat_message", "message": "tweet created" }
)
並在 Angular websocket 服務中
init(userID: number): void{
if(this.ws){
this.ws.close();
}
this.ws = new WebSocket(`${environment.WEBSOCKET_URL}/chat/${userID}/`);
this.ws.onopen = () => {
this.currentWebSocketSubject.subscribe(data => {
if (data) {
this.ws?.send(JSON.stringify(data));
}
});
};
this.ws.onmessage = (event) => {
console.log("message arrived");
console.log(event);
if (event.data) {
const tempData: WS = JSON.parse(event.data) as WS;
switch (tempData.type) {
case 'MESSAGE':
console.log("message arrived");
console.log(tempData);
if (tempData.data) {
this.unreadMessages++;
this.messageSubject.next(tempData);
}
break;
}
}
};
}
當我測試這些代碼時,我使用了兩個客戶端,兩個客戶端登錄,並通過 websockets 成功連接到 django 服務器。 When I create a tweet, django server sends event to every channel using channel_layer.group_send function, and in ChatConsumer class the added "tweet_send" function sends the event to the user. 這些事件分別針對不同的用戶。 但它們都被發送給最后連接 websocket 的用戶。 我不知道為什么。 請幫我。
現在,我正在使用django和angular創建一個網站,並且我想在客戶端和服務器之間添加websocket通信。 我遵循了django通道文檔的說明。( https://channels.readthedocs.io/ )我想從django服務器代碼的任何位置發送任何事件。 但是,當多個用戶通過套接字連接時,從服務器發送的數據將始終流向最后一個連接的用戶。 這就是我所做的。 首先,在consumers.py中,我如下定義了ChatConsumer類,並添加了一個名為“ tweet_send”的新處理函數。
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.room_name
# Join room group
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
...
# here's what I added a new tweet send handler
async def tweet_send(self, event):
content = event['content']
content["group_name"] = self.room_group_name
# Send message to WebSocket
await self.send(text_data=json.dumps({
"type": "MESSAGE",
"data": content
}))
在django服務器端的某個位置(在serializers.py中),當創建新的tweet時,我使用django.channel_layer將新的tweet數據發送給所有用戶
...
def create(self, validated_data):
...
new_tweet.save()
# send message via channels
channel_layer = get_channel_layer()
all_users = list(Member.objects.filter(is_active = True).values_list('id', flat = True))
for user_id in all_users:
async_to_sync(channel_layer.group_send)(
"chat_{}".format(user_id), # this is the group name of group name of individual users.
{ "type": "chat_message", "message": "tweet created" }
)
並在Angular Websocket服務中
init(userID: number): void{
if(this.ws){
this.ws.close();
}
this.ws = new WebSocket(`${environment.WEBSOCKET_URL}/chat/${userID}/`);
this.ws.onopen = () => {
this.currentWebSocketSubject.subscribe(data => {
if (data) {
this.ws?.send(JSON.stringify(data));
}
});
};
this.ws.onmessage = (event) => {
console.log("message arrived");
console.log(event);
if (event.data) {
const tempData: WS = JSON.parse(event.data) as WS;
switch (tempData.type) {
case 'MESSAGE':
console.log("message arrived");
console.log(tempData);
if (tempData.data) {
this.unreadMessages++;
this.messageSubject.next(tempData);
}
break;
}
}
};
}
當測試這些代碼時,我使用了兩個客戶端,兩個客戶端登錄,並成功通過websockets連接到django服務器。 創建推文時,django服務器使用channel_layer.group_send函數將事件發送到每個通道,並且在ChatConsumer類中添加的“ tweet_send”函數將事件發送給用戶。 這些事件分別針對不同的用戶。 但是它們都被發送給了最后一個連接了websocket的用戶。 我不知道為什么請幫我。
我可以看到這個問題已經在這里很久了。 您的代碼存在一個問題,該問題是您的使用者 (tweet_send) 中的推文發送處理程序與您從您的 serializers.py 發送到組的消息類型不匹配。
因此,要解決此問題,您必須重命名推文發送處理程序方法以匹配您發送到組的消息類型,在本例中為chat_message 。 因此,您的推文發送處理程序變為:
# tweet send handler
async def chat_message(self, event):
content = event['content']
content["group_name"] = self.room_group_name
# Send message to WebSocket
await self.send(text_data=json.dumps({
"type": "MESSAGE",
"data": content
}))
我希望這會有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.