python - 是否可以在 Django Channels Consumer 中使用 ZeroMQ 套接字?

标签 python django websocket zeromq django-channels

我有一个 build 自主船的爱好项目。我现在使用 Vuejs 前端和 Django 构建了一个 GUI后端。在此 GUI 中,我可以在 map 上看到船,并向其发送命令。这些命令通过 ZeroMQ sockets 发送效果很好。

我正在使用Django channels通过 websocket 将命令从前端发送到后端,然后通过 ZeroMQ 套接字将其发送到后端。我的消费者(效果很好)如下所示:

import zmq
from channels.generic.websocket import WebsocketConsumer
from .tools import get_vehicle_ip_address, get_vehicle_steer_socket

context = zmq.Context()

class SteerConsumer(WebsocketConsumer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.forward_steer_socket = get_vehicle_steer_socket(context, get_vehicle_ip_address())

    def connect(self):
        self.accept()

    def receive(self, text_data):
        print("Passing on the commands from the frontend:", text_data, "to the boat")
        self.forward_steer_socket.send_string(text_data)

接下来,我还通过 ZeroMQ 套接字从船上接收位置信息,并将其保存到数据库中。我在一个单独的脚本中运行它,前端只需每 2 秒轮询一次后端以获取更新。这是接收船只信息的脚本:

import os
import django
import zmq
os.environ['DJANGO_SETTINGS_MODULE'] = 'server.settings'
django.setup()

# Socket to receive the boat location
context = zmq.Context()
location_socket = context.socket(zmq.SUB)
location_socket.setsockopt(zmq.CONFLATE, True)
location_socket.bind('tcp://*:6001')
location_socket.setsockopt_string(zmq.SUBSCRIBE, '')

while True:
    boat_location = location_socket.recv_json()
    print(boat_location)
    # HERE I STORE THE BOAT LOCATION in the DB

我现在想将此location_socket添加到Consumer,以便Consumer也可以接收ZeroMQ套接字上的船只位置,并且通过 websocket 将其发送到前端。

我当然可以简单地将 location_socket 添加到 Consumer__init__() 方法,如下所示:

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.forward_steer_socket = get_vehicle_steer_socket(context, get_vehicle_ip_address())

    self.location_socket = context.socket(zmq.SUB)
    self.location_socket.setsockopt(zmq.CONFLATE, True)
    self.location_socket.bind('tcp://*:6001')
    self.location_socket.setsockopt_string(zmq.SUBSCRIBE, '')

但我显然不能在 Consumer 中包含 while True 循环。所以从这里我不知道该怎么做。我实际上不知道这是否可能,因为 Django Channels 似乎是专门为 websockets 制作的。我想我可以开始使用多线程或多处理库,但这对我来说是未知的领域。

有人知道是否以及如何在 Django Channel 中创建 ZeroMQ 监听器吗?

最佳答案

可以通过以下方式直接从单独的脚本向您的消费者发送消息: https://channels.readthedocs.io/en/latest/topics/channel_layers.html#using-outside-of-consumers

当新客户端连接到 SteerConsumer 内的消费者时,您将拥有该客户端唯一的 self.channel_name。要向该消费者发送消息,您只需执行(在您的示例中来自单独的脚本):

from channels.layers import get_channel_layer

channel_layer = get_channel_layer()
# "channel_name" should be replaced for the proper name of course
channel_layer.send("channel_name", {
    "type": "chat.message",
    "text": "Hello there!",
})

并在您的 SteerConsumer 方法中添加来处理此消息:

def chat_message(self, event):
    # Handles the "chat.message" event when it's sent to us.
    self.send(text_data=event["text"])

关于python - 是否可以在 Django Channels Consumer 中使用 ZeroMQ 套接字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58832526/

相关文章:

python - ArrayField 中的 Django JSONField

用于在 PHP 网站中聊天的 Node.js

javascript - 以 UTF-8 字符串存储二进制数据

python Tkinter focus_set() 在捕获按键事件时无法正常工作

Python,字符串中的正则表达式: How to remove letter.字母(a.b)?

django - 在连续循环脚本中,数据库数据的更改未反射(reflect)在 Django 查询集中

python - 从 Django 路由到 Angular 路由

c# - C#中读取套接字时算术运算溢出

Python 在使用 pandas 和 str.strip 时崩溃

Python:将 re.sub 用于编码为 &#number; 的 ascii 数字