我编写了一个应用程序,它接收发送方发送的多播数据包(包含音频).我使用过Netty 4并且已经在Windows上运行应用程序,但在Linux上运行时它不会收到多播数据包(Debian Wheezy(raspi)和Ubuntu 12).
我创建了一些可以发送和接收组播数据包的测试代码,结果如下:
发送Windows到Windows工作.
发送Linux到Windows的工作原理.
将Windows发送到Linux,发送但未收到数据包.
我以root身份运行应用程序并将SO_BROADCAST设置为true.
我错过了什么?
如果我使用标准的Java MulticastSocket而不是Netty,那么该应用程序可以运行,但我更喜欢使用Netty,因为它易于使用并简化了代码.
测试代码是:
public class TestMulticast { private int port = 51972; private Logger log = Logger.getLogger(this.getClass()); private InetAddress remoteInetAddr = null; private InetSocketAddress remoteInetSocket = null; private InetAddress localInetAddr = null; private InetSocketAddress localInetSocket = null; private DatagramChannel ch = null; private EventLoopGroup group = new NioEventLoopGroup(); private boolean bSend = false; public TestMulticast(String localAddress, String remoteAddress, String sPort, boolean bSend) { this.bSend = bSend; try { localInetAddr = InetAddress.getByName(localAddress.trim()); remoteInetAddr = InetAddress.getByName(remoteAddress.trim()); } catch (Exception e) { log.error("Error creating InetAddresses. Local: " + localAddress + " Remote: " + remoteAddress, e); } try { port = Integer.parseInt(sPort); } catch (Exception e) { log.error("Error Parsing Port: " + sPort, e); } } public void run() throws Exception { log.debug("Run TestMulticast, Send Packet = " + bSend); try { localInetSocket = new InetSocketAddress(port); remoteInetSocket = new InetSocketAddress(remoteInetAddr, port); Bootstrap b = new Bootstrap(); b.group(group); b.channelFactory(new ChannelFactory() { @Override public Channel newChannel() { return new NioDatagramChannel(InternetProtocolFamily.IPv4); } }); b.option(ChannelOption.SO_BROADCAST, true); b.option(ChannelOption.SO_REUSEADDR, true); b.option(ChannelOption.IP_MULTICAST_LOOP_DISABLED, false); b.option(ChannelOption.SO_RCVBUF, 2048); b.option(ChannelOption.IP_MULTICAST_TTL, 255); b.handler(new LoggingHandler(LogLevel.DEBUG)); log.debug("Am I Logged on as ROOT: " + PlatformDependent.isRoot()); ch = (DatagramChannel) b.bind(localInetSocket).sync().channel(); log.debug("Result of BIND: " + ch.toString()); if (remoteInetAddr.isMulticastAddress()) { NetworkInterface nic = NetworkInterface.getByInetAddress(localInetAddr); ChannelFuture future = ch.joinGroup(remoteInetSocket, nic); log.debug("Result of Join: " + future.toString()); } else { log.debug("############NOT A MULTICAST ADDRESS: '" + remoteInetAddr.getHostAddress() + "'"); } if (bSend) { group.scheduleAtFixedRate(new Runnable() { @Override public void run() { try { Date date = new Date(); byte[] bytes = date.toString().getBytes(); ByteBuf buffer = Unpooled.copiedBuffer(bytes); DatagramPacket packet = new DatagramPacket(buffer, remoteInetSocket, localInetSocket); ch.writeAndFlush(packet); } catch (Exception e) { log.error("Error Sending DatagramPacket", e); } } }, 0, 10, TimeUnit.SECONDS); } } catch (Exception e) { log.error(e); } } public void stop() { try { if (ch != null) { try { ch.close(); } catch (Exception e) { log.error("Error Closing Channel", e); } } group.shutdownGracefully(); } catch (Exception e) { log.error("Error ShuutingDown", e); } }
}
编辑:
如果发现我的问题,我应该学习阅读文档!
对于Mutlicast,您应该绑定到WILDCARD地址.
所以将代码更改为
localInetSocket = new InetSocketAddress(remotePort);
....
ch = (DatagramChannel) b.bind(localInetSocket).sync().channel();
....
if (remoteInetAddr.isMulticastAddress()) { NetworkInterface nic = NetworkInterface.getByInetAddress(localInetAddr); ChannelFuture future = ch.joinGroup(remoteInetSocket, nic); log.debug("Result of Join: " + future.toString()); }
我已经使用新的更改修改了上面的完整代码.
皮特.