消息类型websocket.group_send没有处理程序,如何修复?

aydmsdu9  于 2023-08-05  发布在  其他
关注(0)|答案(2)|浏览(93)

我从一个用户的WebSocket连接切换到聊天室,两个人可以互相连接,但在切换时,在接收方法中,现在需要group_send,然后它停止工作,如何修复?
完整追溯

> Exception inside application: No handler for message type
> websocket.group_send   File
> "D:\Dev\Web\Chaty\lib\site-packages\channels\sessions.py", line 183,
> in __call__
>     return await self.inner(receive, self.send)   File "D:\Dev\Web\Chaty\lib\site-packages\channels\middleware.py", line 41,
> in coroutine_call
>     await inner_instance(receive, send)   File "D:\Dev\Web\Chaty\lib\site-packages\channels\consumer.py", line 59, in
> __call__
>     [receive, self.channel_receive], self.dispatch   File "D:\Dev\Web\Chaty\lib\site-packages\channels\utils.py", line 52, in
> await_many_dispatch
>     await dispatch(result)   File "D:\Dev\Web\Chaty\lib\site-packages\channels\consumer.py", line 75, in
> dispatch
>     raise ValueError("No handler for message type %s" % message["type"])   No handler for message type websocket.group_send
> WebSocket DISCONNECT /messages/dildo/ [127.0.0.1:58910]

字符串
消费者

import asyncio
import json
from django.contrib.auth import get_user_model
from channels.consumer import AsyncConsumer
from channels.db import database_sync_to_async

from .models import Thread, ChatMessage


class ChatConsumer(AsyncConsumer):

    async def websocket_connect(self, event):
        print('Connected', event)
        other_user = self.scope['url_route']['kwargs']['username']
        me = self.scope['user']
        thread_obj = await self.get_thread(me, other_user)
        chat_room = f"thread_{thread_obj.id}"
        self.chat_room = chat_room
        await self.channel_layer.group_add(
            chat_room,
            self.channel_name
        )

        await self.send({
            'type':'websocket.accept'
        })

    async def websocket_receive(self, event):
        print('Recive', event)

        front_response = event.get('text', None)

        if front_response is not None:
            compiled_response_data = json.loads(front_response)

            if 'FormData' in compiled_response_data:
                pass
        author = str(self.scope['user'])

        Response_ = {
            'Message': compiled_response_data['FormData']['message'],
            'Author': author
        } 

        new_event = {
            'type':'websocket.send',
            'text': json.dumps(Response_)

        }
        print(new_event)
        await self.channel_layer.group_send(
            self.chat_room,
            new_event
        )
    async def websocket_disconnect(self, event):
        print('Disconnected', event)

    @database_sync_to_async
    def get_thread(self, user, other_username):
        return Thread.objects.get_or_new(user, other_username)[0]


我的html模板

{% extends "base.html" %}

{% block content %}
<h3>Thread for {% if user != object.first %}{{ object.first }}{% else %}{{ object.second }}{% endif %}</h3>
<ul id='chat-items'>
{% for chat in object.chatmessage_set.all %}

<li>{{ chat.message }} via {{ chat.user }}</li>

{% endfor %}
</ul>

<form id='form' method='POST'> {% csrf_token %}
{{form }}
<input type="text" name='porn'>
<input type="text" name='pov'>
<button type='submit' class='btn btn-primary'>Submit</button>
</form>

{% endblock %}

{% block script %}

<script>
    const from_user = '{{ object.first }}',
        to_user = '{{ object.second }}';
// websocket scripts
    let loc = window.location,
        path_first_part = 'ws://',
        path_second_part = loc.host + loc.pathname,
        endpoint = '',
        FormItself = $('#form'),
        FormData = $('#form input'),
        DataHolder = {},
        ChatItself = $("#chat-items");
    if (loc.protocol == 'https:'){
        path_first_part = 'wss://'
    }else{
        path_first_part = 'ws://'
    }
    endpoint = path_first_part + path_second_part
    let socket = new WebSocket(endpoint);

    socket.onmessage = function(e){
        console.log('Message', e);
        let parset_data = JSON.parse(e.data),
            Chat_MSG =  parset_data.Message,
            Chat_AUTHOR =  parset_data.Author;

        ChatItself.append('<li>' + Chat_MSG + ' <= via => ' + Chat_AUTHOR + '</li>');

    };
    socket.onopen = function(e){
        console.log('Open', e)
        FormItself.submit(function(event){
            event.preventDefault();
            DataHolder['FormData'] = {};
            FormData.each(function(key, value){
                DataHolder['FormData'][value.name] = value.value;
                value.value = '';
            })
            socket.send(JSON.stringify(DataHolder));
        })
        console.log(DataHolder)
    };
    socket.onerror = function(e){
        console.log('Error', e)
    };
    socket.onclose = function(e){
        console.log('Close', e)
    };

</script>
{% endblock %}


看起来你的帖子大部分都是代码;请补充一些细节。

2skhul33

2skhul331#

兄弟,很高兴能帮到你,我自己也碰到过一个,只要你建了一个群,那么你就需要向群里发消息,也就是在WebSocket_receive里给type: 'websocket.send'放一个回调函数,在那里你已经可以使用向websocket发消息了。

new_event = {
            'type':'chat_message',
            'text': json.dumps(Response_)

        }

字符串
接下来创建chat_message回调函数

async def chat_message(self, event):
    print('\n',event)
    front_response = event.get('text', None)
    if front_response is not None:
        compiled_response_data = json.loads(front_response)
    Response_ = {
        'Message': compiled_response_data['Message'],
        'Author': compiled_response_data['Author']
    } 

    # Send message to WebSocket
    await self.send({
        'type':'websocket.send',
        'text': json.dumps(Response_)
    })


最后你的消费者会是这样的。

import asyncio
import json
from django.contrib.auth import get_user_model
from channels.consumer import AsyncConsumer
from channels.db import database_sync_to_async

from .models import Thread, ChatMessage


class ChatConsumer(AsyncConsumer):

    async def websocket_connect(self, event):
        print('Connected', event)
        other_user = self.scope['url_route']['kwargs']['username']
        me = self.scope['user']
        thread_obj = await self.get_thread(me, other_user)
        chat_room = f"thread_{thread_obj.id}"
        self.chat_room = chat_room
        await self.channel_layer.group_add(
            chat_room,
            self.channel_name
        )

        await self.send({
            'type':'websocket.accept'
        })

    async def websocket_receive(self, event):
        print('Recive', event)

        front_response = event.get('text', None)

        if front_response is not None:
            compiled_response_data = json.loads(front_response)

            if 'FormData' in compiled_response_data:
                pass
        author = str(self.scope['user'])

        Response_ = {
            'Message': compiled_response_data['FormData']['message'],
            'Author': author
        } 

        new_event = {
            'type':'chat_message',
            'text': json.dumps(Response_)

        }
        await self.channel_layer.group_send(
            self.chat_room,
            new_event
        )
    async def websocket_disconnect(self, event):
        print('Disconnected', event)

    # Receive message from room group
    async def chat_message(self, event):
        print('\n',event)
        front_response = event.get('text', None)
        if front_response is not None:
            compiled_response_data = json.loads(front_response)
        author = str(self.scope['user'])
        Response_ = {
            'Message': compiled_response_data['Message'],
            'Author': author
        } 
        message = event['text']

        # Send message to WebSocket

        await self.send({
            'type':'websocket.send',
            'text': json.dumps(Response_)
        })

    @database_sync_to_async
    def get_thread(self, user, other_username):
        return Thread.objects.get_or_new(user, other_username)[0]

    #saving to db
    @database_sync_to_async
    def create_chat_message(self, author, msg):
        thread_obj = self.thread_obj
        return ChatMessage.objects.create(thread=thread_obj, user=author, message=msg)

7ivaypg9

7ivaypg92#

简短回答:
检查是否有其他消费者具有相同的组名称,但没有所需的处理程序。每个消费者类都必须有一个唯一的组名,除非您特别希望这样做。
详细回答:
我遇到了类似的问题。我让消费者连接到组“user_1”。当向组“user_1”发送消息时,我得到异常“应用程序内部异常:没有消息类型“new.message”的处理程序,连接已关闭。

class MyFirstConsumer(JsonWebsocketConsumer):
    def connect(self):
        user = self.scope['user']
        if not user:
            self.close()
        else:
            async_to_sync(self.channel_layer.group_add)(f'user_{user.id}', self.channel_name)
            self.accept()

    def new_message(self, event):
        data = {
            'msg_type': 'new_message',
            'data': event['data']
        }
        self.send_json(data)

字符串
在深入研究代码后,我发现有2个不同的消费者连接到同一个组。

class MySecondConsumer(JsonWebsocketConsumer):
    def connect(self):
        user = self.scope['user']
        if not user:
            self.close()
        else:
            async_to_sync(self.channel_layer.group_add)(f'user_{user.id}', self.channel_name)
            self.accept()

    # no handler here "new_message"

    def some_another_handler(self, event):
        data = {
            'msg_type': 'new_message',
            'data': event['data']
        }
        self.send_json(data)


当通过

await channel_layers.group_send(
    'user_1',
    {
        'type': 'new.message',
        'data': {
            'text': 'some_text'
        }
    }
)


两个消费者都接收消息。第一个消费者(我认为这是问题所在)处理了它,没有错误,但第二个消费者没有正确的处理程序。因此,在第二个消费者中发生了前导错误。我为不同的消费者更改了组名,一切都正常工作。

class MyFirstConsumer(JsonWebsocketConsumer):
    def connect(self):
        user = self.scope['user']
        if not user:
            self.close()
        else:
            async_to_sync(self.channel_layer.group_add)(f'user_first_consumer_{user.id}', self.channel_name)
            self.accept()

    def new_message(self, event):
        data = {
            'msg_type': 'new_message',
            'data': event['data']
        }
        self.send_json(data)

class MySecondConsumer(JsonWebsocketConsumer):
    def connect(self):
        user = self.scope['user']
        if not user:
            self.close()
        else:
            async_to_sync(self.channel_layer.group_add)(f'user_second_consumer_{user.id}', self.channel_name)
            self.accept()

    # no handler here "new_message"

    def some_another_handler(self, event):
        data = {
            'msg_type': 'new_message',
            'data': event['data']
        }
        self.send_json(data)


发送地不要忘了改群名

await channel_layers.group_send(
    'user_first_consumer_1',
    {
        'type': 'new.message',
        'data': {
            'text': 'some_text'
        }
    }
)

相关问题