Использование JZMQ с EPGM Transport не отправляет и не принимает данные

Я экспериментирую с zmq со вкусом java, чтобы проверить преимущества использования PGM по сравнению с TCP в моем проекте. Поэтому я изменил пример погоды из руководства zmq, чтобы использовать транспорт epgm. Все компилируется и запускается, но ничего не отправляется и не принимается. Если я перевожу транспорт обратно на TCP, сервер получает сообщения, отправленные клиентом, и я получаю ожидаемый вывод на консоль.

Итак, каковы требования для использования PGM? Я изменил строку, которую я передаю методам bind и connect, чтобы следовать zmq api для zmq_pgm: "transport://interface; адрес многоадресной рассылки:port". Это не сработало. Я получаю и неверный аргумент ошибки всякий раз, когда я пытаюсь использовать этот формат. Итак, я упростила это, отбросив интерфейс и точку с запятой, которые "работают", но я не получаю никаких результатов.

Мне не удалось найти пример jzmq, который использует pgm/epgm, а в документации api для привязки java не определен соответствующий формат строки для конечной точки, передаваемой для связывания или соединения. Так чего мне здесь не хватает? Нужно ли использовать разные хосты для клиента и сервера?

Следует отметить, что мой код выполняется на виртуальной машине VirtualBox (хост Ubuntu 14.04/OSX Mavericks). Я не уверен, что это как-то связано с проблемой, с которой я сейчас сталкиваюсь.

Сервер:

public class wuserver {

public static void main (String[] args) throws Exception {
    //  Prepare our context and publisher
    ZMQ.Context context = ZMQ.context(1);

    ZMQ.Socket publisher = context.socket(ZMQ.PUB);
    publisher.bind("epgm://xx.x.x.xx:5556");
    publisher.bind("ipc://weather");

    //  Initialize random number generator
    Random srandom = new Random(System.currentTimeMillis());
    while (!Thread.currentThread ().isInterrupted ()) {
        //  Get values that will fool the boss
        int zipcode, temperature, relhumidity;
        zipcode = 10000 + srandom.nextInt(10000) ;
        temperature = srandom.nextInt(215) - 80 + 1;
        relhumidity = srandom.nextInt(50) + 10 + 1;

        //  Send message to all subscribers
        String update = String.format("%05d %d %d", zipcode, temperature, relhumidity);
        publisher.send(update, 0);
    }

    publisher.close ();
    context.term ();
   }
}

Клиент:

public class wuclient {

public static void main (String[] args) {
    ZMQ.Context context = ZMQ.context(1);

    //  Socket to talk to server
    System.out.println("Collecting updates from weather server");
    ZMQ.Socket subscriber = context.socket(ZMQ.SUB);
    //subscriber.connect("tcp://localhost:5556");
    subscriber.connect("epgm://xx.x.x.xx:5556");

    //  Subscribe to zipcode, default is NYC, 10001
    String filter = (args.length > 0) ? args[0] : "10001 ";
    subscriber.subscribe(filter.getBytes());

    //  Process 100 updates
    int update_nbr;
    long total_temp = 0;
    for (update_nbr = 0; update_nbr < 100; update_nbr++) {
        //  Use trim to remove the tailing '0' character
        String string = subscriber.recvStr(0).trim();

        StringTokenizer sscanf = new StringTokenizer(string, " ");
        int zipcode = Integer.valueOf(sscanf.nextToken());
        int temperature = Integer.valueOf(sscanf.nextToken());
        int relhumidity = Integer.valueOf(sscanf.nextToken());

        total_temp += temperature;

    }
    System.out.println("Average temperature for zipcode '"
            + filter + "' was " + (int) (total_temp / update_nbr));

    subscriber.close();
    context.term();
  }
}

2 ответа

Еще один момент, о котором следует помнить, это то, что некоторые среды виртуализации -RHEV/Ovirt и libvirt/KVM с включенной опцией mac_filter - приходят к выводу, что по умолчанию у всех людей есть возможность использовать таблицы (eb|ip) для использования mcast между гостями, Конечно, в случае libvirt решение состоит в том, чтобы просто установить опцию на "0" и перезапустить libvirtd. RHEV/Ovirt требуется специальный плагин.

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

Есть пара возможностей:

  • Вы должны убедиться, что ZMQ скомпилирован с --with-pgm вариант: смотрите здесь - но это не является вашей проблемой, если вы не видите "протокол не поддерживается"
  • Используя сырье pgm требуются права суперпользователя, потому что требуется возможность создавать необработанные сокеты... но epgm не требует этого, так что это не должно быть вашей проблемой (я только поднимаю это, потому что вы используете термин "pgm / epgm", и вы должны знать, что они не одинаково доступны во всех ситуациях)
  • На самом деле проблема в вашем случае заключается в том, что pgm / epgm требует поддержки по сетевому пути. Теоретически, это требует поддержки вашего маршрутизатора, поэтому ваше приложение может отправить одно сообщение, и ваш маршрутизатор должен отправить несколько сообщений каждому клиенту, но если ваш сервер достаточно осведомлен, он, вероятно, может немедленно отправить несколько сообщений и обойти это. поддержка роутера. Проблема в том, что, как вы правильно догадались, попытка сделать все это на одном хосте не поддерживается.

Итак, вам нужны разные хосты для клиента и сервера.

Другие вопросы по тегам