我使用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说:
“此套接字选项的初始/默认值可能为null,以指示操作系统将选择传出接口,通常是基于网络路由表。
但是输入的数据是什么。方法"join“总是要求指定网络接口,它不允许我传递null。
理想情况下,我希望加入多播组,在默认情况下,与此多播组用于传出数据报的接口完全相同。
有什么办法吗?
我正在使用Java 8和Linux操作系统。
发布于 2020-01-14 15:35:44
DatagramChannel API中没有明确支持在系统选择的接口上加入多播组,但是可以通过使用MulticastSocket::getNetworkInterface获得占位符NetworkInterface来解决这个问题。所以这应该能做你想做的事
NetworkInterface ni;
try (MulticastSocket s = new MulticastSocket()) {
ni = s.getNetworkInterface();
}
MembershipKey key = channel.group(join, ni);
创建MulticastSocket完全是为了调用getNetworkInterface。
发布于 2020-01-14 11:50:31
TL;博士--我不认为它能以你想要的方式工作。至少在Java里没有。
关于D类(多播)地址的问题是,它们对几乎所有有能力的NIC都是有效的。发送和接收之间没有一致性,即使对于同一个多播组也是如此。我可以在一个接口上发送到229.111.222.333
,并在另一个接口上连接/侦听同一个多播组。由于UDP是无会话的,这种设置是非常好的。
即使操作系统能够选择合适的接口,它们中的大多数也不能,这就是为什么您需要指定它。但是,如果机器充当一个多播路由器(例如运行mrouted
),那么这就完全不同了,因为它的路由功能通常由/etc/mrouted.conf
控制。
例如,如果我用两个NIC转储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
时,它进一步支持它,而它显然不是。
“此套接字选项的初始/默认值可能为null,以指示操作系统将选择传出接口,通常是基于网络路由表。
我不认为这是一个完全准确的陈述。或者,如果您在一个多主框上,并且其中一个接口上设置了MULTICAST
标志,则可能是这样。但是如果您有几个,那么您也许可以使用ip add route
显式地添加一个特定的路由/NIC,但我怀疑它是否有效。
多年来,我在多个操作系统中所做或使用的所有多播编程和商业产品都要求我指定要在哪个NIC上执行操作。
https://stackoverflow.com/questions/59718752
复制相似问题