10

Is it possible to receive data from more than one multicast group on a single socket?

For example:

void AddGroup(int sock,
              const char* mc_addr_str,
              int mc_port,
              const char* interface) {
  struct sockaddr_in mc_addr;
  memset(&mc_addr, 0, sizeof(mc_addr));
  mc_addr.sin_family      = AF_INET;
  mc_addr.sin_addr.s_addr = inet_addr(mc_addr_str);
  mc_addr.sin_port        = htons(mc_port);

  if ((bind(sock, (struct sockaddr *) &mc_addr,
            sizeof(mc_addr))) < 0) {
    perror("bind() failed");
    exit(1);
  }

  // construct an IGMP join request structure
  struct ip_mreq mc_req;
  mc_req.imr_multiaddr.s_addr = inet_addr(mc_addr_str);
  mc_req.imr_interface.s_addr = inet_addr(interface);

  if ((setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                  (void*) &mc_req, sizeof(mc_req))) < 0) {
    perror("setsockopt() failed");
    exit(1);
  }
}

This code works when I add one multicast group. But when I try to add another, the "bind" fails. I don't quite understand why the bind needs to be there in the first place? (but the code doesn't work without it).

Ideally I would like to call AddGroup multiple times on the same socket. Is this possible? Or do I need one socket per group and then just use polling?

Puppy
  • 144,682
  • 38
  • 256
  • 465
Switch
  • 5,126
  • 12
  • 34
  • 40

6 Answers6

8

You can join as many multicast groups as you like, using the appropriate setsockopt() call with the IP_ADD_MEMBERSHIP option, rather than bind().

user207421
  • 305,947
  • 44
  • 307
  • 483
  • When I remove the "bind" on subsequent calls to AddGroup, only the first multicast group seems to get "subscribed" to. – Switch Feb 14 '12 at 00:53
  • @Switch If a group isn't reachable via your default IP route you need to specify the appropriate outbound local address when joining the group, so the 'add membership' IGMP message goes in the appopriate direction. – user207421 Aug 03 '12 at 01:05
3

You can join as many multicast groups you want to on a single socket. See setsockopt(), IP_PKTINFO for a way to recognize which multicast group you are reading data from.

3

You only bind a socket once. Skip the bind the second time and see what happens.

bmargulies
  • 97,814
  • 39
  • 186
  • 310
2

bind to the passive address, i.e. 0.0.0.0 for IPv4 and use ASM or SSM to pull in additional groups, e.g. IP_ADD_MEMBERSHIP as listed.

You can only bind once.

Steve-o
  • 12,678
  • 2
  • 41
  • 60
0

Yes, it's possible: look on the example in the link (http://www.tenouk.com/Module41c.html) To shorten this up in a few steps:

  1. You setsockopt with SO_REUSEADDR
  2. You bind on INADDR_ANY
  3. You setsockopt with IP_ADD_MEMBERSHIP on every group you want to receive datagram from.
  4. It seems to me that using IP_PKTINFO gives an option to distinguish received packets, but sender must take care about preparing them(Setting the source IP for a UDP socket)
Community
  • 1
  • 1
bambo
  • 3
  • 2
0

In unix based OSes:

If you need to bind to multicast address, you cannot call bind() more than once. And you will need to bind to multicast address when you expect more than one multicast streams using same destination port and multiple processes running in same device receiving those multicasts.

For example, when you have multicast streams: 239.0.0.1:1234, 239.0.0.2:1234, 239.0.0.3:1234 and 239.0.0.4:1234, and you want to receive 239.0.0.1, 239.0.0.2 in process-A and want to receive 239.0.0.3, 239.0.0.4 in process-B, you cannot accomplish this when both processes A and B running in same device.

nullptr
  • 3,320
  • 7
  • 35
  • 68