Java 多播套接字未在特定网络接口上接收

Java multicast socket not receiving on specific network interface

我有一个多播套接字,我必须在其中指定一个网络接口才能接收数据。但是,当我使用网络接口 Java 加入群组时,将不会收到它。我有一个简单的 python 程序,它在同一台服务器上执行完全相同的操作并且工作正常。

在 Java 中为 MulticastSocket 设置网络接口时我遗漏了什么?

java是:

    SocketAddress socketAddress =  new InetSocketAddress("x.x.x.x", 40000);
    NetworkInterface networkInterface = NetworkInterface.getByInetAddress(InetAddress.getByName("z.z.z.z"));

    logger.info("Network interface is {} ", networkInterface);

    MulticastSocket s = new MulticastSocket();
    s.setInterface(InetAddress.getByName("z.z.z.z"));
    s.joinGroup(socketAddress,networkInterface);
    logger.info(s.getNetworkInterface());

while(true){

            try{

                logger.info("Waiting for message");
                byte[] size = new byte[2];

                DatagramPacket recv = new DatagramPacket(size, size.length);
                socket.receive(recv);

                logger.info("Received size message"); //Never get here
                ByteBuffer wrapped = ByteBuffer.wrap(size); // big-endian by default
                short messageSize = wrapped.getShort(); 

                byte[] buf = new byte[messageSize-2];
                DatagramPacket message = new DatagramPacket(buf, buf.length);
                socket.receive(message);

                logger.info("Received multicast message");
                dataQueue.put(buf);
            }catch(Exception e){ 
                logger.error("Failed to receive multicast message ",e);
            }
        }

这样做的结果是我从未收到任何数据包。我有一个简单的 python 程序,它做同样的事情,而且每次都能完美运行。

供参考 python 看起来像

MCAST_GRP = 'x.x.x.x'
MCAST_PORT = 40000

mcastsock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
mcastsock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
mcastsock.setsockopt(socket.SOL_IP,socket.IP_ADD_MEMBERSHIP,
                socket.inet_aton(MCAST_GRP)+socket.inet_aton('z.z.z.z'))
mcastsock.bind((MCAST_GRP,MCAST_PORT))

while True:
  print mcastsock.recv(1320)

使用 nio 包将其切换到 MulticastChannel 解决了这个问题。不完全确定这是原因,但底层接口是 igmp v3,在某些情况下,上面的 java 多播代码似乎不适用于该配置。

这里有更多详细信息和代码示例: https://docs.oracle.com/javase/7/docs/api/java/nio/channels/MulticastChannel.html

 // join multicast group on this interface, and also use this
 // interface for outgoing multicast datagrams
 NetworkInterface ni = NetworkInterface.getByName("hme0");

 DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)
     .setOption(StandardSocketOptions.SO_REUSEADDR, true)
     .bind(new InetSocketAddress(5000))
     .setOption(StandardSocketOptions.IP_MULTICAST_IF, ni);

 InetAddress group = InetAddress.getByName("225.4.5.6");

 MembershipKey key = dc.join(group, ni);