我正在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
答案 0 :(得分:0)
事实证明,在Linux上,默认行为是多路复用流量,这样当绑定到0.0.0.0时,将收到该端口上所有组的所有组播流量。
由于默认行为,应用程序必须过滤掉不需要的组的流量。出于安全原因,这是必要的,确保应用程序仅接收预期的流量。
还有一个名为IP_MULTICAST_ALL的套接字选项,显然可以设置(它在Java中不是标准的,所以我不确定如何),这将强制堆栈实现所需的非标准行为。