1

プロジェクトで TCP 経由で PGM を使用する利点をテストするために、Java フレーバーの zmq を試しています。そこで、天気の例を zmq ガイドから、epgm トランスポートを使用するように変更しました。すべてがコンパイルされて実行されますが、何も送受信されていません。トランスポートを TCP に戻すと、サーバーはクライアントから送信されたメッセージを受信し、期待どおりのコンソール出力が得られます。

では、PGM を使用するための要件は何ですか? bind メソッドと connect メソッドに渡す文字列を変更し、zmq_pgm の zmq API に従っています: "transport://interface;multicast address:port"。それはうまくいきませんでした。この形式を使用しようとすると、無効な引数エラーが発生します。そのため、「機能する」インターフェイスとセミコロンを削除して単純化しましたが、結果が得られません。

pgm/epgm を使用する jzmq の例を見つけることができず、Java バインディングの API ドキュメントでは、バインドまたは接続に渡されるエンドポイントの適切な文字列形式が定義されていません。それで、私はここで何が欠けていますか?クライアントとサーバーに異なるホストを使用する必要がありますか?

注目すべき点の 1 つは、VirtualBox VM (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();
  }
}
4

2 に答える 2

0

いくつかの可能性があります:

  • ZMQ が--with-pgmオプションでコンパイルされていることを確認する必要があります:ここを参照- ただし、「サポートされていないプロトコル」が表示されない場合、これは問題ではないようです。
  • raw を使用pgmするには、raw ソケットを作成する機能が必要なため、root 権限が必要です...しかしepgm、それは必要ないので、あなたの問題でもありません (「pgm /epgm」という用語を使用しているため、私はそれを取り上げるだけです。また、すべての状況で同じように利用できるわけではないことに注意してください)。
  • あなたのケースで実際に問題と思われるのは、pgm/epgm がネットワーク パスに沿ってサポートを必要とすることです。理論的には、ルーターへのサポートが必要なため、アプリケーションは単一のメッセージを送信し、ルーターに複数のメッセージを各クライアントに送信させることができますが、サーバーが十分に認識している場合、おそらく複数のメッセージをすぐに送信してこれをバイパスできますルーターのサポート。問題は、ご想像のとおり、これをすべて 1 つのホストで実行しようとすることはサポートされていないことです。

したがって、クライアントとサーバーには異なるホストが必要です。

于 2014-05-27T16:13:36.000 に答える
0

注意すべきもう 1 つのビットは、いくつかの仮想化環境 (mac_filter オプションが有効になっている RHEV/Ovirt および libvirt/KVM) が頭に浮かぶことです。 . もちろん、libvirt を使用する場合の解決策は、単純にオプションを「0」に設定して libvirtd を再起動することです。RHEV/Ovirt にはカスタム プラグインが必要です。

いずれにせよ、使用している各システムのネットワーク デバイスにスニファを配置し、一方のホストから出るトラフィックが他方のホストで実際に見えることを確認することをお勧めします。

于 2014-06-09T19:00:16.393 に答える