6

I'm making an application where there is a certain thread (MulticastListenerThread) which has a MulticastSocket and is listening for UDP (datagram) packets sent to the multicast group the socket is listening too.

This works. I can join a multicast group, send a message to that group and receive it through the MulticastSocket.

However, I would like to determine, from the receiver point of view, from which multicast group he received the packet. The following code gives me the address of the originator of the packet, not the multicast group:

DatagramPacket packet = new DatagramPacket(buf, buf.length);
mlcSenderSocket.receive(packet);
String src_addr = packet.getAddress().getHostAddress();

The code for sending the packet is as follows:

InetAddress address = InetAddress.getByName(dest);
packet = new DatagramPacket(payload, payload.length,
    address, mlcEventPort);
LLog.out(this,"[NC] MLC packet Sent to ev port MLC " + mlcEventPort
    + " and to addr " + address);
mlcSenderSocket.send(packet);

Is it at all possible to determine which group sent the packet?

Edit:

It appears this isn't possible. In terms of performance impact (I'm working for IoT devices), would assigning a socket per multicast group (and hence, a listener thread per group) be viable? Potentially many groups may be joined (in terms of tens or hundreds even). If it is viable, then I just need to keep the joined group address somewhere manually and refer to it as necessary. Suggestions for other work arounds are welcome!

  • I suppose a work-around would be to maintain multiple `MulticastSocket` objects, one for each group you wish to join. It would then be easy enough to keep track of the association between sockets and groups. – Duncan Jones Dec 19 '14 at 08:03
  • I did think of that but it does seem overly excessive, especially since I there could be potentially many groups to join and this is (in theory) meant for constrained IoT devices. I'd then be required to have a listener thread per MulticastSocket, something I'd prefer not to do. –  Dec 19 '14 at 08:15

2 Answers2

2

No group sent the packet. A socket at a specific IP address sent the packet, and the source IP address is available in the DatagramPacket. Multicast packets aren't sourced from multicast groups, they are addressed to multicast groups.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I understand. But still, the socket only accepts the packet because he has joined a certain group, so at some level the information about from which group the packet originates has to be available, no? Like the comment to my main post said, if I have only a single group per socket, this information would be obvious, but I have multiple. –  Dec 19 '14 at 09:05
  • The socket that sent the packet may have joined zero groups, or several. The concept of which group sent it therefore has no meaning. What you really need is which group the packet was sent *to,* and that information is available at the C level, but not as far as I'm aware at the Java level, unless it shows up in the revisions to `DatagramSocketChannel.` – user207421 Dec 19 '14 at 09:13
  • Unfortunate. Thanks for the reply, I edited my main post with a small new question. –  Dec 19 '14 at 09:34
  • I don't see any problem at all with tens of sockets, and probably not with hundreds. I would try it that way and see if you have a problem. If you do, you can reduce the threading requirement by using a `java.nio.channels.DatagramSocketChannel` in non-blocking mode, in conjunction with a `Selector.` – user207421 Dec 19 '14 at 10:10
0

Yes it's true that you can join a MulticastSocket to multiple groups, for example:

InetAddress group;

MulticastSocket s=new MulticastSocket(12345);
NetworkInterface ni=NetworkInterface.getByName("eth1");

group=InetAddress.getByName("239.255.10.10");
s.joinGroup(new InetSocketAddress(group,12345),ni);

group=InetAddress.getByName("239.255.10.11");
s.joinGroup(new InetSocketAddress(group,12345),ni);

You then receive datagrams like this:

DatagramPacket datagram=s.receive(datagram);

Unfortunately there is no java API call in the DatagramPacket object that will allow you to determine which of the two groups was targetted by the sender, all you can get is the IP address of the network interface on which it was received (from the socket) and the sender's IP address (from the datagram).

To achieve what you want to do you're going to need to create multiple MulticastSocket objects and listen to one group per socket. You could use your own threads or NIO to listen on them all simultaneously.

Andy Brown
  • 11,766
  • 2
  • 42
  • 61
  • You can't 'get the IP address of the network interface on which it was received' in Java. You can get the IP address from which it was sent. – user207421 Dec 19 '14 at 10:08
  • Yes of course you can, that's all vanilla standard and available on the socket object. It's the MC group info that can't be retrieved from the received datagram. My text was unclear as to what you can get from where. I've clarified it. – Andy Brown Dec 19 '14 at 10:15
  • You can get the interface to which the socket is bound, *if* it's bound to an interface. If it's bound to INADDR_ANY, as it usually is, you can't. – user207421 Dec 19 '14 at 19:56