How to use multicast on a multi-user system (Java, Linux)

This is in Java, but if necessary, I can always return to C through JNI.

I have a system with two network adapters, each of which is connected to a separate subnet. I want to use multicast (specifically SDP) to discover other hosts on both networks.

One network is simple: create a MulticastSocket on the specified port, joinGroup it, and I get the packets. Simplicity.

Two networks: not yet possible. I tried:

1) create two sockets, bind to the same port and use setInterface () or setNetworkInterface () to "connect" to the correct interface. No luck, even after various permutations of setReuseAddress ().

2) create one socket and then try to join twice, with two calls to joinGroup (SocketAddress mcastaddr, NetworkInterface netIf). The second connection call fails.

Solutions outside of Java would be great. In particular, if I could configure multicast routes that would effectively “combine” the two interfaces (I could then look at each packet to determine which network), which would be nice. As I mentioned earlier, in this environment you can use any amount of embedded code (Linux, with the java Apache "luni" infrastructure).

Thanks!

+4
source share
4 answers

By the way, I recently worked on a similar problem.

Here is some Java code that does what you want - it collects SDP packages on multiple interfaces. joinGroup is used to "attach" to specified interfaces.

/** * Demonstrate multi-homed multicast listening * * usage: java Multihome eth0 eth1 lo <etc> */ import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.MulticastSocket; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; import java.util.HashSet; import java.util.Set; public class Multihome { // SDP constants public static final String MULTICAST_ADDRESS = "239.255.255.250"; public static final int MULTICAST_PORT = 1900; // args: each arg is the name of an interface. public void doMain(Set<String> args) throws Exception { InetSocketAddress socketAddress = new InetSocketAddress(MULTICAST_ADDRESS, MULTICAST_PORT); MulticastSocket socket = new MulticastSocket(MULTICAST_PORT); Enumeration<NetworkInterface> ifs = NetworkInterface.getNetworkInterfaces(); while (ifs.hasMoreElements()) { NetworkInterface xface = ifs.nextElement(); Enumeration<InetAddress> addrs = xface.getInetAddresses(); String name = xface.getName(); while (addrs.hasMoreElements()) { InetAddress addr = addrs.nextElement(); System.out.println(name + " ... has addr " + addr); } if (args.contains(name)) { System.out.println("Adding " + name + " to our interface set"); socket.joinGroup(socketAddress, xface); } } byte[] buffer = new byte[1500]; DatagramPacket packet = new DatagramPacket(buffer, buffer.length); while (true) { try { packet.setData(buffer, 0, buffer.length); socket.receive(packet); System.out.println("Received pkt from " + packet.getAddress() + " of length " + packet.getLength()); } catch (IOException ex) { ex.printStackTrace(); } } } public static void main(String[] args) throws Exception { Set<String> argSet = new HashSet<String>(); Multihome multi = new Multihome(); for (String arg : args) { argSet.add(arg); } multi.doMain(argSet); } } 
+7
source

I would recommend using JGroups , which abstracts everything that you are trying to do, if I understand your needs correctly. it is an elegant and well-designed structure for multicast (and multicast semantics emulated if necessary).

+2
source

I don't have a reasonable setup to try this here, but when you receive multicast messages, you don’t need to bind MulticastSocket to the port number from the multicast address, and setNetworkInterface is used to set the interface used for outgoing messages.

That I would try to create two different MulticastSockets (on any free port), and then use joinGroup (SocketAddress mcastaddr, NetworkInterface netIf) for each of them, using the same multicast address, but with different network interfaces.

0
source

Have you considered using ZeroConf for this?

The jmdns project has a clean Java implementation that should work very well.

0
source

All Articles