Django 通过 websocket 向所有客户端发送事件

Posted

技术标签:

【中文标题】Django 通过 websocket 向所有客户端发送事件【英文标题】:Django send events via websocket to all clients 【发布时间】:2021-11-29 18:50:34 【问题描述】:

我想通过 websocket 将事件(json 字符串)发送给所有客户端(发送给所有通过 websocket 建立连接的人)。我的代码:

我觉得asgi和路由都可以

asgi.py

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'base_app.settings')
django.setup()
application = ProtocolTypeRouter(
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter(
            websocket_urlpatterns
        )
    ),
)

routing.py

from api_producer.consumers import EventWebSocket

websocket_urlpatterns = [
    url('ws/start/', EventWebSocket.as_asgi()),
]

问题点: 某些函数会生成事件,我想将这些事件发送给客户端

from api_producer.consumers import EventWebSocket

def event_producer():
    my_socket = EventWebSocket()
    my_socket.receive("Some_text")

consumers.py

from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync


class EventWebSocket(WebsocketConsumer):
    def connect(self):
        self.channel_name = "CHANNEL_1"
        print("CALL_ACCEPT")
        async_to_sync(self.channel_layer.group_add)("global", self.channel_name)
        self.accept()

    def disconnect(self, close_code):
        async_to_sync(self.channel_layer.group_discard)("global", self.channel_name)

    def receive(self, text_data):
        print("RRR_ receive ", text_data)
        async_to_sync(self.channel_layer.group_send)(
            "global",
            
                "type": "global.message",
                "text": text_data,
            ,
        )

    def chat_message(self, event):
        print("CHAT_MESSAGE")
        self.send(text_data=event["text"])
    
    def global_event(self, event):
        print("GLOB_MESSAGE")
        self.send(text_data=event["text"])

我的行动: 1 前往 websocketKing 并发送请求 ws://127.0.0.1:8000/ws/start/。日志输出:

WebSocket HANDSHAKING /ws/start/ [127.0.0.1:37194]
WebSocket HANDSHAKING /ws/start/ [127.0.0.1:37194]
CALL_ACCEPT
HTTP POST /api/start_detection/ 200 [0.57, 127.0.0.1:37238] (trigger event_producer)

发送事件的正确方法是什么?

【问题讨论】:

你需要在你的消费者的connect方法中调用self.accept()来完成握手并完成连接 谢谢,已添加。但我有错误:``` 'EventWebSocket' 对象没有属性 'channel_layer``` (在 def receive() 中) 您不应该像在event_producer 中那样初始化EventWebSocket 对象并在其上调用receive。您需要获取一个通道层并向您的所有消费者都是成员的组/通道发送消息 @IainShelvington 你能详细说明一下吗?如何获取通道层? 添加了一个有望证明这个想法的答案 【参考方案1】:

您应该通过通道层发送事件,you can use channel layers outside of consumers like this

from channels.layers import get_channel_layer
channel_layer = get_channel_layer()

def event_producer():
    async_to_sync(channel_layer. group_send)("global", 
        "type": "global.event",
        "text": "foo"
    )

然后在您的消费者中加入事件生产者发送事件的全局通道,并添加一个可由事件生产者触发的方法。您可以重复使用“聊天”频道...

class EventWebSocket(WebsocketConsumer):
    def connect(self):
        ...
        async_to_sync(self.channel_layer.group_add)("global", self.channel_name)
        self.accept()

    ...

    def global_event(self, event):
        self.send(text_data=event["text"])

【讨论】:

根据您的帖子更新了我的代码。但我没有收到任何事件(日志中没有 GLOB_MESSAGE 和 CHAT_MESSAGE 输出)

以上是关于Django 通过 websocket 向所有客户端发送事件的主要内容,如果未能解决你的问题,请参考以下文章

Django:通过 websocket 定期发送更新

如何使用 WCF NetHttpBinding(WebSockets)通过服务器向所有客户端广播(推送)一个客户端发送的消息?

python测试开发django-81.dwebsocket实现websocket

通过 websocket 继续向客户端发送数据

无法通过 websocket 从服务器向客户端发送数据

Websocket在playframework 2中向所有客户端发送数据