如何在单个 ZMQ 发送请求中同时发送图像(ndarray)和字符串数据
How to send both image(ndarray) and string data in single ZMQ send request
对于发送字符串数据,以下代码有效:
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())
处理多部分消息时请考虑以下事项:
- 所有消息部分只会在您发送最后一部分后发送。
- 接收方将始终接收所有消息部分或 none。
在您的具体示例中,您已经在 send_array
函数中使用标志 zmq.SNDMORE
编写了多部分消息。我们还可以通过添加带有 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))
.
对于发送字符串数据,以下代码有效:
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())
处理多部分消息时请考虑以下事项:
- 所有消息部分只会在您发送最后一部分后发送。
- 接收方将始终接收所有消息部分或 none。
在您的具体示例中,您已经在 send_array
函数中使用标志 zmq.SNDMORE
编写了多部分消息。我们还可以通过添加带有 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))
.