Многоадресная передача между приложениями на одном хосте

Из того, что я читал, должно быть возможно, чтобы два приложения на одном хосте могли отправлять и получать дейтаграммы через многоадресную рассылку. Я пытался реализовать это, используя следующий код Java (который представляет собой слегка измененную версию того, что дано в Javadoc для MulticastSocket):

    public static void main(String[] args) throws IOException{

        NetworkInterface nic = NetworkInterface.getByName("wlan4");

        int port = 6789;
        InetAddress group = InetAddress.getByName("228.5.6.7");
        MulticastSocket s = new MulticastSocket(port);
        s.setNetworkInterface(nic);
        s.joinGroup(group);

        if(args.length > 0 && args[0].equals("send")){
            System.out.println("SEND MODE");
            String msg = "Hello";
            DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(),
                                    group, port);
            s.send(hi);
        }else{

            byte[] buf = new byte[1000];
            DatagramPacket recv = new DatagramPacket(buf, buf.length);

            System.out.println("RECEIVE MODE");
            s.receive(recv);
            System.out.println(MessageFormat.format("Received: {0}",
                new String(recv.getData()).trim()));

            s.leaveGroup(group);
        }
    }

Если я запустил приведенный выше код, указав send в качестве входного аргумента, программа выполнится нормально, она отправит пакет, а затем завершится. Однако, если я хочу получить пакет, программа блокируется методом приема, поскольку она никогда не получает дейтаграмму. Я протестировал это, запустив несколько экземпляров приложения на своей машине, как с одним, так и с несколькими получателями и одним отправителем. Non получает любое сообщение в любое время.

Если я, с другой стороны, разрешаю приложению получать то, что оно только что отправило (запустив метод приема безоговорочно в зависимости от того, отправляет ли приложение), оно отлично работает только для этого приложения. Это заставляет меня поверить, что экземпляр JVM имеет эксклюзивную привязку к этому сокету, не позволяя другим использовать его (даже если опция getReuseAddress() возвращает true для MulticastSockets).

Я работаю под Windows 10 и проверил, что UDP-пакет отправляется в сеть с помощью Wireshark, поэтому я решил, что это связано с тем, что пакет не доставляется в два приложения.

Что я могу сделать, чтобы два приложения могли взаимодействовать через многоадресную рассылку по одному и тому же номеру порта?

РЕДАКТИРОВАТЬ:

Общая идея состоит в том, чтобы сервер отправлял дейтаграмму всем слушающим клиентам в выбранной сети (поэтому сетевая карта указана в примере как «wlan4»), независимо от того, где они выполняются (например, на том же хосте, что и сервер. или не).


person chrillof    schedule 09.03.2019    source источник
comment
Почему вы заставляете многоадресный сокет использовать wlan4, когда вся необходимая связь находится внутри локального хоста?   -  person user207421    schedule 09.03.2019
comment
Хорошая мысль, и я понимаю, что, возможно, не объяснил свои общие намерения. Идея состоит в том, чтобы отправитель отправлял дейтаграмму, чтобы ее перехватили все клиенты в сети, независимо от того, находятся ли клиенты на том же хосте, что и сервер, или нет.   -  person chrillof    schedule 09.03.2019
comment
Вы отключили кольцевую передачу многоадресной рассылки? Мне кажется, что вы получаете только петли, и что ваш joinGroup() вообще не вступил в силу за пределами вашего локального хоста. Попробуйте просто удалить строку setNetworkInterface().   -  person user207421    schedule 11.03.2019
comment
Есть ли явная причина, по которой отправителю нужно, чтобы порт источника пакета совпадал с портом назначения (6789 в вашем примере)? В противном случае было бы намного проще заставить отправителя отправлять пакет из произвольного DatagramSocket, открытого только для этой цели. Обратите внимание, что при отправке дейтаграммы отправителю все равно, является ли пункт назначения адресом mcast или unicast, т.е. вам не нужен MulticastSocket для отправки сообщения mcast.   -  person dan.m was user2321368    schedule 23.06.2020


Ответы (1)


После некоторой отладки я понял, что могу получать многоадресные пакеты от нескольких приложений, если само приложение отправляло и получало многоадресные дейтаграммы. Оказывается, отправка пакета в группу многоадресной рассылки каким-то образом запускает эту функцию. Мне это кажется ошибкой.

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

        byte[] buf = new byte[1000];
        DatagramPacket recv = new DatagramPacket(buf, buf.length);
        s.send(new DatagramPacket("A".getBytes(), 1, group, port));
        s.receive(recv);

        System.out.println("RECEIVE MODE");
        s.receive(recv);
        System.out.println(MessageFormat.format("Received: {0}",
                new String(recv.getData()).trim()));

        s.leaveGroup(group);
person chrillof    schedule 10.03.2019
comment
Это не кажется правильным. NB Вы должны использовать new String(recv.getData(), 0, recv.getLength()). - person user207421; 11.03.2019