我有一个多播套接字,我必须指定一个网络接口才能接收数据。但是,当我使用网络接口加入组时,Java将无法接收它。我有一个简单的python程序,在同一台服务器上执行完全相同的操作,并且工作正常。
在为Java中的MulticastSocket设置NetworkInterface时我缺少什么?
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)
答案 0 :(得分:1)
使用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);