Netty 4在Linux上接收多播数据包

 唇边那烟味世界 发布于 2023-01-17 10:23

我编写了一个应用程序,它接收发送方发送的多播数据包(包含音频).我使用过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());
        }

我已经使用新的更改修改了上面的完整代码.

皮特.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有