Как отправить данные изображения (ndarray) и строки в одном запросе на отправку ZMQ - PullRequest
0 голосов
/ 29 октября 2018

Для отправки строковых данных работают следующие коды:

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 )

Но мне нужно отправить оба строковых сообщения вместе с файлом изображения. Есть ли способ добавить сообщение в тот же запрос?

Любые идеи приветствуются! Спасибо

1 Ответ

0 голосов
/ 21 ноября 2018

Полагаю, вы ищете составные сообщения , которые позволяют составлять сообщения из нескольких кадров. Реализация 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())

При работе с составными сообщениями учитывайте следующее:

  • Все части сообщения будут отправлены только после отправки последней части.
  • Получатель всегда будет либо получать все части сообщения, либо ни одной вообще.

В вашем конкретном примере вы уже составляете составные сообщения в функции send_array, используя флаг zmq.SNDMORE. Мы можем расширить ваш пример, также добавив строковые данные с флагом zmq.SNDMORE. Вот сторона server :

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))

Этот код основан на примере Сериализация сообщений с PyZMQ и адаптирован для работы с Python 3. Для Python 2 рассмотрите возможность использования buffer(msg) вместо bytes(memoryview(msg)).

...