在一个套接字上订阅多个组播组(Linux,C)

10

一个socket能否接收来自多个组播组的数据?

例如:

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);
  }
}

当我添加一个多播组时,这段代码可以工作。但是当我尝试添加另一个多播组时,“绑定”失败了。我不太明白为什么一开始需要有“绑定”?(但是如果没有它,代码无法工作)。

理想情况下,我希望在同一个套接字上多次调用AddGroup。这可行吗?还是我需要为每个组使用一个套接字,然后只使用轮询?

6个回答

8

您可以使用适当的setsockopt()调用IP_ADD_MEMBERSHIP选项,而不是bind(),加入任意多个组播组。


当我在对AddGroup进行后续调用时去掉"bind",只有第一个多播组似乎被"订阅"了。 - Switch
@Switch如果一个组无法通过默认IP路由到达,则在加入组时需要指定适当的出站本地地址,以便“添加成员”IGMP消息朝着适当的方向发送。 - user207421

3
您可以在单个套接字上加入尽可能多的组播组。请参考 setsockopt(),IP_PKTINFO 了解如何识别您正在从哪个组播组读取数据。

3

你只需要绑定一次socket。跳过第二次绑定,看看会发生什么。


2

bind到被动地址,即IPv4的0.0.0.0,并使用ASM或SSM来拉取其他组,例如列出的IP_ADD_MEMBERSHIP

您只能bind一次。


0

在基于Unix的操作系统中:

如果您需要绑定到多播地址,则不能调用bind()超过一次。当您期望使用相同目标端口和在同一设备上运行的多个进程接收这些多播时,您将需要绑定到多播地址。

例如,当您有多播流:239.0.0.1:1234、239.0.0.2:1234、239.0.0.3:1234和239.0.0.4:1234,并且您想在进程A中接收239.0.0.1、239.0.0.2,并想在进程B中接收239.0.0.3、239.0.0.4时,当进程A和B都在同一设备上运行时,您无法完成此操作。


0

是的,这是可能的:请查看链接中的示例(http://www.tenouk.com/Module41c.html) 为了简化操作,您可以按照以下几个步骤进行:

  1. 使用SO_REUSEADDR设置setsockopt
  2. 在INADDR_ANY上绑定
  3. 对您想要从中接收数据报的每个组使用IP_ADD_MEMBERSHIP设置setsockopt。
  4. 我认为使用IP_PKTINFO可以区分接收到的数据包,但发送方必须注意准备它们(为UDP套接字设置源IP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接