0

我正在 Suse Linux 上使用 Netty 3.6.5.Final 和 JDK7 (Nio.2) 实现一个 UDP 服务器,但我已经碰壁了。该问题专门处理在 Windows 和 MacOS 与 Linux 上绑定到通配符地址 (0.0.0.0) 的差异。

我有一个用于发送数据的多播组和一个用于接收数据的组,它们都绑定到同一个端口。当我尝试在出站组上发布时,我将数据包返回到入站组,这不是 bueno。在 windows/mac 上,这不是问题。一个Linux它得到“混杂”的行为。

在 Linux 上,绑定通配符地址会导致绑定端口上的所有 UDP 流量被传递,而不管组成员身份如何(因此是上面的示例)。对于 MacOS/Windows,您只能从您通过 joinGroup() 订阅的组中获得流量。后者是期望的行为。

Linux 的准解决方案是绑定到您有兴趣从中接收流量的多播组地址。这对于您加入的第一个组(恰好是您绑定的组地址)非常有用。但是,如果您想使用同一订阅者通过 joinGroup() 加入其他组,则不会传递额外的组流量。

我还尝试绑定到默认 NIC 的 IP 地址,并且根本没有传输任何流量。

所以我试过:

if(SystemUtils.IS_OS_MAC_OSX || SystemUtils.IS_OS_WINDOWS) {
    socketAddress = new InetSocketAddress(port);
} else {
    socketAddress = new InetSocketAddress(getUnixBindAddress(), port);
}
groupChannel = (DatagramChannel)bootstrap.bind(socketAddress);      

其中 getUnixBindAddress() 获取默认的 NIC IP 地址。在这种情况下没有流量被传递。

我也试过:

if(SystemUtils.IS_OS_MAC_OSX || SystemUtils.IS_OS_WINDOWS) {
    socketAddress = new InetSocketAddress(port);
} else {
    socketAddress = new InetSocketAddress(multicastAddress, port);
}
groupChannel = (DatagramChannel)bootstrap.bind(socketAddress);      

其中 multicastAddress 是要加入的第一个组的地址。仅传递来自第一个加入组的流量。

我的 joinGroup() 调用如下所示:

ChannelFuture future = groupChannel.joinGroup(new InetSocketAddress(group.getGroupAddress(), group.getPort()), networkInterface);
future.syncUninterruptibly();

和这样的引导代码:

bootstrap = new ConnectionlessBootstrap(new NioDatagramChannelFactory(
    Executors.newSingleThreadExecutor(), InternetProtocolFamily.IPv4));
bootstrap.setOption("broadcast", false);
bootstrap.setOption("loopbackModeDisabled", true);
bootstrap.setOption("reuseAddress", true);
bootstrap.setPipelineFactory(this);

如果有人对如何使多个组订阅在 Linux 上为 Netty 工作有任何见解,我将不胜感激。

-布赖恩

4

1 回答 1

0

事实证明,在 Linux 上,默认行为是多路复用流量,这样当绑定到 0.0.0.0 时,该端口上的所有组都会收到所有多播流量。

由于默认行为,应用程序必须从不需要的组中过滤掉流量。出于安全原因,这是必要的,因为它可以确保应用程序只接收预期的流量。

还有一个名为 IP_MULTICAST_ALL 的套接字选项显然可以设置(它在 Java 中不是标准的,所以我不确定如何设置),这将强制堆栈实现所需的非标准行为。

于 2013-05-08T22:58:14.280 回答