python - 如何在单个 ZMQ 发送请求中同时发送图像(ndarray)和字符串数据

标签 python sockets zeromq pyzmq

对于发送字符串数据,以下代码有效:

context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:5667")
socket.send_string("my string data")

对于发送图像(ndarray),以下代码有效:

def send_array(socket, img, flags=0, copy=True, track=False):
    """send a numpy array with metadata"""
    md = dict(
        dtype = str(img.dtype),
        shape = img.shape,
    )
    socket.send_json(md, flags|zmq.SNDMORE)
    return socket.send(img, flags, copy=copy, track=track)

context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:5667")
send_array(socket, my_ndarray_image )

但我确实需要将字符串消息与图像文件一起发送。有没有办法在同一个请求中附加消息?

欢迎任何想法! 谢谢

最佳答案

我猜你正在寻找 multipart messages ,它允许您使用多个框架来撰写消息。 Python 实现 pyzmq 已经为我们提供了一个很好的多部分消息包装器。以下是服务器发送多部分消息的示例:

context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:5555")

time.sleep(0.2)  # wait for socket to be properly bound

socket.send_multipart([b"first part", b"second part"])

客户端接收多部分消息:

context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.setsockopt(zmq.SUBSCRIBE, b"")
socket.connect("tcp://localhost:5555")

print(socket.recv_multipart())

在处理多部分消息时请考虑以下事项:

  • 所有消息部分只会在您发送最后一部分后发送。
  • 接收方将始终收到所有消息部分或根本没有。

在您的特定示例中,您已经使用标志 zmq.SNDMOREsend_array 函数中编写了多部分消息。我们还可以通过添加带有 zmq.SNDMORE 标志的字符串数据来扩展您的示例。这是服务器端:

def send_array_and_str(socket, img, string, flags=0):
    md = dict(dtype = str(img.dtype), shape=img.shape)

    socket.send_string(string, flags | zmq.SNDMORE)
    socket.send_json(md, flags | zmq.SNDMORE)
    return socket.send(img, flags)

context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:5667")
time.sleep(0.2)

my_ndarray = np.array([1, 2, 3])
my_string = "Hello World"
send_array_and_str(socket, my_ndarray, my_string)

以及接收消息的客户端代码:

def recv_array_and_str(socket, flags=0, copy=True, track=False):
    string = socket.recv_string(flags=flags)
    md = socket.recv_json(flags=flags)
    msg = socket.recv(flags=flags, copy=copy, track=track)

    img = np.frombuffer(bytes(memoryview(msg)), dtype=md['dtype'])
    return string, img.reshape(md['shape'])

context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.setsockopt(zmq.SUBSCRIBE, b"")
socket.connect("tcp://localhost:5667")

print(recv_array_and_str(socket))

此代码基于示例 Serializing messages with PyZMQ并适用于 Python 3。对于 Python 2,请考虑使用 buffer(msg) 而不是 bytes(memoryview(msg))

关于python - 如何在单个 ZMQ 发送请求中同时发送图像(ndarray)和字符串数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53049141/

相关文章:

python - pandas Dataframe isna 基于多个条件更新

c - 在c socket程序中定义结构的疑问

c++ - 如何在 C++ 中使用 ZeroMQ 发送包含数组的结构时解决错误

c++ - zeroMQ:zmq_recv() 不起作用

python - 如何在 Django 的 Replace 函数中使用正则表达式

python - 将列表插入特定索引处的二维列表

javascript - agent.maxSockets 的真正含义是什么?

c - 如何使用原始套接字 ping 本地主机?

python - 从并发请求的分布式工作中发回正确的信息

python - 如何从 Telegram Bot 的群组消息中获取 User 对象