For sending string data, following codes works :
context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:5667")
socket.send_string("my string data")
For sending image(ndarray) following code works :
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 )
But I do need to send both the string message along with the image file. Is there any way to append the message in the same request ?
Any ideas are welcomed ! Thanks
I guess you are looking for multipart messages, which allow you to compose a message out of several frames.
The Python implementation pyzmq
already provides us with a nice wrapper for multipart messages. Here is an example for the server sending a multipart message:
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"])
And the client receiving a multipart message:
context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.setsockopt(zmq.SUBSCRIBE, b"")
socket.connect("tcp://localhost:5555")
print(socket.recv_multipart())
Please consider the following when working with multipart messages:
In your specific example, you are already composing a multipart messages in the send_array
function by using the flag zmq.SNDMORE
. We can extend your example by also adding the string data with the zmq.SNDMORE
flag. Here is the server side:
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)
And the client code receiving the message:
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))
This code is based on the example Serializing messages with PyZMQ and adapted to work with Python 3. For Python 2, consider using buffer(msg)
instead of bytes(memoryview(msg))
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With