Я пытаюсь использовать epgm
транспорт в моей простой программе издатель-подписчик, но я не могу этого сделать. Насколько я понимаю, я не могу предоставить правильную строку адреса в bind
а также connect
заявления.
Издатель и подписчик могут работать на одном или разных компьютерах.
Ниже приведен необходимый код, который использует tcp
транспорт и работает правильно. Оно использует cppzmq
: https://github.com/zeromq/cppzmq.
Код издателя:
#include <zmq.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int main () {
zmq::context_t context (1);
zmq::socket_t publisher (context, ZMQ_PUB);
publisher.bind("tcp://10.1.1.8:5000");
int i = 0;
while (1) {
int topic = 101;
zmq::message_t message(50);
snprintf ((char *) message.data(), 50, "%03d %10d %10d", topic, i, i);
//fprintf(stderr, "message: %s\n", (char *) message.data());
publisher.send(message);
++i;
}
return 0;
}
Абонентский код:
#include <zmq.hpp>
#include <iostream>
#include <sstream>
#include <unistd.h>
#include <cassert>
int main (int argc, char *argv[]) {
zmq::context_t context (1);
zmq::socket_t subscriber (context, ZMQ_SUB);
subscriber.connect("tcp://10.1.1.8:5000");
const char *filter = "101 ";
subscriber.setsockopt(ZMQ_SUBSCRIBE, filter, strlen (filter));
zmq::message_t tp;
int maxx = 0;
for (int i = 0; i < 1000; ++i) {
zmq::message_t update;
int topic, a, b;
if(subscriber.krecv(&update, ZMQ_DONTWAIT)) {
//fprintf(stderr, "size of data received: %zd\n", sizeof(update.data()));
std::istringstream iss(static_cast<char*>(update.data()));
iss >> topic >> a >> b;
assert(a == b);
}
else {
--i;
}
maxx = a > maxx ? a : maxx;
}
fprintf(stderr, "maxx = %d\n", maxx);
return 0;
}
krecv
метод, который используется в подписчике:
inline bool krecv (message_t *msg_, int flags_ = 0) {
int nbytes = zmq_msg_recv (&(msg_->msg), ptr, flags_);
if (nbytes >= 0)
return true;
if (zmq_errno () == EAGAIN)
return false;
return false;
}
Я пытался изменить bind
Заявление в редакцию:
publisher.bind("epgm://10.1.1.8:5000");
publisher.bind("epgm://224.1.1.1:5000");
publisher.bind("epgm://eth0;224.1.1.1:5000");
publisher.bind("epgm://10.1.1.8;224.1.1.1:5000");
publisher.bind("epgm://localhost:5000");
Для всех 5 случаев программа вылетает с Assertion failed: false (src/pgm_socket.cpp:165)
, Для 5-го случая (epgm://localhost:5000
), Я также получаю следующие предупреждения вместе с аварией:
Warn: Interface lo reports as a loopback device.
Warn: Interface lo reports as a non-multicast capable device.
Как я могу решить эту проблему? Я предполагаю, что смена адреса будет одинаковой как у издателя, так и у подписчика?
я использую libpgm 5.2.122
с zeromq-4.1.3
,
Обратите внимание, что машина имеет следующие интерфейсы:
eth0
(Ethernet) — inet адрес:10.1.1.8
ib0
(InfiniBand) — inet addr:10.1.3.8
lo
(Локальная петля) — inet addr:127.0.0.1
Попробуйте 239.0.0.0/8
IP в вашей привязке:
publisher.bind("epgm://;239.0.0.1:5000");
Диапазон 239.0.0.0/8 назначается RFC 2365 для частного использования в организации. Из RFC пакеты, предназначенные для адресов многоадресной рассылки IPv4 в административном отношении, не пересекают административно определенные организационные границы, а адреса многоадресной рассылки IPv4 в административном отношении назначаются локально и не должны быть глобально уникальными.
я использовал epgm
с zeromq
на Linux, и это сложно настроить правильно
Предполагая, что вы используете Linux, читайте ниже, если нет, у меня нет опыта работы с Windows, так что не обращайте внимания:
epgm
не работает с адаптером обратной связи в Linux, так что забудьте об этом.eth0
должно сработать. Является MCAST
определенно включен (проверьте ifconfg
)?Я ссылку zeromq
с openpgm
и есть некоторые довольно специфические различия в том, как повторное использование порта работает между различными ядрами Linux.
Я добавил немного кода в openpgm
репо, чтобы исправить мои проблемы с rhel7
https://github.com/steve-o/openpgm/pull/52
Джеймс