Можно ли повторно использовать zmq :: message_t после отправки? - PullRequest
0 голосов
/ 29 апреля 2018

Я использую ZeroMQ для реализации игрушечного протокола связи; и я впервые использую этот фреймворк / библиотеку.

Теперь в моем протоколе несколько последовательных сообщений отправляются определенной стороной, и все они имеют одинаковый размер. Итак, я подумал, что не буду перераспределять их, а просто попытался повторно заполнить буфер данных сообщения другим контентом, например ::1003

zmq::message_t msg { fixed_common_size };
while (some_condition()) {
    my_filling_routine(msg.data(), fixed_common_size);
    the_socket.send(msg);
}

но на второй итерации этого цикла я получаю ошибку сегментации; msg.data() - это не nullptr. Мне пришло в голову, что, возможно, ZeroMQ каким-то образом каннибализирует память, и поэтому мне нужно написать что-то вроде:

zmq::message_t msg { fixed_common_size };
char buffer[fixed_common_size];
while (some_condition()) {
    my_filling_routine(buffer, fixed_common_size);
    msg.rebuild(buffer, fixed_common_size);
    the_socket.send(msg);
}

Но я уверен, что это вызывает перераспределение и перераспределение.

Итак, действительно ли это так, что rebuild() необходим, или это просто ошибка в моем коде?

Примечание: я использую сокеты Unix, на случай, если ответ каким-то образом зависит от этого.

1 Ответ

0 голосов
/ 29 апреля 2018

Можно ли повторно использовать zmq::message_t после отправки?

Ну короче - нет, не могу

Во-первых, добро пожаловать в ZeroMQ, отличное место для .

API ZeroMQ предупреждает об этих проблемах в явном виде. Успешный вызов zmq_msg_send(), ссылающийся на полезную нагрузку сообщения, не означает, что само сообщение действительно было отправлено.

Лучше всего попытаться представить, что вызов просто "перемещает" ответственность от кода вашего приложения к движку ZeroMQ (внутри фабрики с пулом IOthreads, созданным в экземпляре Context()) ...).

Структура zmq_msg_t, переданная zmq_msg_send(), обнуляется во время вызова.

и еще лучше никогда прикасайтесь к нему в любое время позже, как сообщалось выше: o)

Максимальный «экологический» обход распределителя заключается в повторном использовании сообщения целом , как:

Если вы хотите отправить одно и то же сообщение в несколько сокетов, вы должны скопировать его, используя (например, используя zmq_msg_copy()).


Бонусное предупреждение при копировании ...

плюс еще один поднятый вопрос: может копировать, но посмел попытаться изменить его после этого ...

Избегайте изменения содержимого сообщения после того, как сообщение было скопировано с помощью zmq_msg_copy(), это может привести к неопределенному поведению. Если вам нужна настоящая печатная копия, выделите новое сообщение с помощью zmq_msg_init_size() и скопируйте содержимое сообщения с помощью memcpy().

Никогда не обращайтесь к членам zmq_msg_t напрямую, вместо этого всегда используйте zmq_msg семейство функций.

...