加入多个组不适用于SuSe Linux和JDK7上的Netty 3.6.5.Final

时间:2013-05-08 00:27:01

标签: linux netty nio java-7 multicast

我正在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()加入其他组,则不会传递其他组流量。

我也尝试绑定到默认网卡的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进行多个群组订阅有任何见解,我将非常感激。

-Brian

1 个答案:

答案 0 :(得分:0)

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

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

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