java NIO присоединяется к многоадресному каналу на сетевом интерфейсе по умолчанию - PullRequest
0 голосов
/ 13 января 2020

Я использую java .nio.channels.DatagramChannel для отправки и получения многоадресных сообщений UDP. Коробка, на которой запущена моя программа, может иметь несколько сетевых интерфейсов.

Я могу указать сетевой интерфейс вручную, используя опцию сокета для исходящих дейтаграмм:

NetworkInterface ni = NetworkInterface.getByName("eth0");
channel.setOption(StandardSocketOptions.IP_MULTICAST_IF, ni);

и передавая сетевой интерфейс для метода соединения для входящих датаграмм:

MembershipKey key = channel.join(group, ni);

Но я Мне бы хотелось, чтобы мое приложение использовало интерфейс по умолчанию на основе таблиц маршрутизации. Для исходящих данных это легко. Я не должен указывать IP_MULTICAST_IF или передавать null в качестве сетевого интерфейса. Java do c говорит следующее:

"Начальное / значение по умолчанию этой опции сокета может быть нулевым, чтобы указать, что исходящий интерфейс будет выбран операционной системой, как правило, на основе таблицы сетевой маршрутизации. "

Но что насчет входящих данных. Метод "join" всегда требует указания сетевого интерфейса, и он не позволяет мне передавать значение NULL.

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

Есть ли способ сделать это?

Я использую Java 8 и Linux ОС.

Ответы [ 2 ]

1 голос
/ 14 января 2020

В DatagramChannel API нет явной поддержки для присоединения к многоадресной группе на интерфейсе, выбранном системой, но вы можете обойти это, используя MulticastSocket :: getNetworkInterface для получения заполнителя NetworkInterface. Так что это должно делать то, что вы хотите:

NetworkInterface ni;
try (MulticastSocket s = new MulticastSocket()) {
    ni = s.getNetworkInterface();
}

MembershipKey key = channel.group(join, ni);

MulticastSocket создается исключительно для вызова getNetworkInterface.

1 голос
/ 14 января 2020

TL; DR Я не думаю, что можно заставить работать так, как вы хотите. По крайней мере, не в Java.

Особенность адресов класса D (многоадресная) заключается в том, что они действительны практически для любого способного NI C. Нет никакой согласованности между отправкой и получением даже для одной и той же многоадресной группы. Я могу отправить на 229.111.222.333 на одном интерфейсе и присоединиться / прослушать ту же группу многоадресной рассылки на другом. Так как UDP не требует сеансов, настройки такого рода идеально подходят.

Даже если ОС смогла выбрать правильный интерфейс, большинство из них не могут, и поэтому вам нужно указать его. Если машина работает как многоадресный маршрутизатор (например, работает mrouted), то это совсем другое дело, поскольку ее возможности маршрутизации обычно контролируются /etc/mrouted.conf.

Например, если я дам дамп таблица маршрутизации для моего Windows ящика с двумя сетевыми картами (я знаю, что вы используете Linux, но обычно он не отображает записи таблицы маршрутизации для адресов класса D. И я считаю, что это подсказка ;-)), я получил это (нерелевантные записи опущены):

Network Destination        Netmask          Gateway       Interface  Metric
        224.0.0.0        240.0.0.0         On-link         127.0.0.1    131
        224.0.0.0        240.0.0.0         On-link       192.168.1.1    281
        224.0.0.0        240.0.0.0         On-link    172.89.123.123    281

Как вы можете видеть, если я отправляю или слушаю, скажем, 224.123.123.123, ОС не будет иметь понятия, какой интерфейс выбрать, все они одинаково приемлемый может использовать значение Metric, но в этом случае использование многоадресной передачи в интерфейсе обратной связи не имеет смысла. Адреса класса D являются странными птицами, что дополнительно поддерживается "конечным адресом" 240.0.0.0 выше, помеченным как Netmask, когда это явно не так.

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

Я не думаю, что это абсолютно точное утверждение. Или это может быть, если вы работаете в многодомном ящике и на одном интерфейсе установлен флаг MULTICAST. Но если у вас их несколько, то возможно вы можете использовать ip add route для явного добавления спецификаций c route / NI C, но я сомневаюсь, что это сработает.

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

...