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

时间:2021-01-27 18:10:30

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?

理想情况下,我想在同一个套接字上多次调用AddGroup。这可能吗?或者我是否每组需要一个套接字然后才使用轮询?

6 个解决方案

#1


6  

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

您可以使用适当的setsockopt()调用和IP_ADD_MEMBERSHIP选项(而不是bind())来加入任意数量的组播组。

#2


3  

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

您只绑定一次套接字。第二次跳过绑定,看看会发生什么。

#3


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.

绑定到被动地址,即对于IPv4为0.0.0.0,并使用ASM或SSM来引入其他组,例如列出的IP_ADD_MEMBERSHIP。

You can only bind once.

你只能绑定一次。

#4


2  

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.

您可以在单个套接字上加入所需数量的多播组。有关识别要从中读取数据的多播组的方法,请参阅setsockopt(),IP_PKTINFO。

#5


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:

是的,这是可能的:查看链接中的示例(http://www.tenouk.com/Module41c.html)通过以下几个步骤简化此操作:

  1. You setsockopt with SO_REUSEADDR
  2. 你使用SO_REUSEADDR setockopt

  3. You bind on INADDR_ANY
  4. 您绑定INADDR_ANY

  5. You setsockopt with IP_ADD_MEMBERSHIP on every group you want to receive datagram from.
  6. 在要从其接收数据报的每个组上使用IP_ADD_MEMBERSHIP setockopt。

  7. 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)
  8. 在我看来,使用IP_PKTINFO提供了区分收到的数据包的选项,但发送者必须注意准备它们(设置UDP套接字的源IP)

#6


-3  

I do not believe it possible to join more than one multicast group on a given socket. The socket is defined by the pairing of the source ip/port and destination ip/port. The operating system would not know what to do with data that comes down from the second ip/port because it would not have a socket to send it to.

我不相信可以在给定套接字上加入多个多播组。套接字由源IP /端口和目标IP /端口的配对定义。操作系统不知道如何处理来自第二个ip / port的数据,因为它没有套接字来发送它。

The bind is necessary to register the connection with the operating system. It's basically like registering a file handle.

绑定是注册与操作系统的连接所必需的。它基本上就像注册文件句柄一样。

The best way to do this would be to create a socket for each multicast group and then call select(). select() will inform you if any socket has data ready for reading.

执行此操作的最佳方法是为每个多播组创建一个套接字,然后调用select()。如果任何套接字已准备好读取数据,select()将通知您。

Check your man pages for more info on socket(), bind(), and select().

有关socket(),bind()和select()的更多信息,请查看手册页。

#1


6  

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

您可以使用适当的setsockopt()调用和IP_ADD_MEMBERSHIP选项(而不是bind())来加入任意数量的组播组。

#2


3  

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

您只绑定一次套接字。第二次跳过绑定,看看会发生什么。

#3


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.

绑定到被动地址,即对于IPv4为0.0.0.0,并使用ASM或SSM来引入其他组,例如列出的IP_ADD_MEMBERSHIP。

You can only bind once.

你只能绑定一次。

#4


2  

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.

您可以在单个套接字上加入所需数量的多播组。有关识别要从中读取数据的多播组的方法,请参阅setsockopt(),IP_PKTINFO。

#5


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:

是的,这是可能的:查看链接中的示例(http://www.tenouk.com/Module41c.html)通过以下几个步骤简化此操作:

  1. You setsockopt with SO_REUSEADDR
  2. 你使用SO_REUSEADDR setockopt

  3. You bind on INADDR_ANY
  4. 您绑定INADDR_ANY

  5. You setsockopt with IP_ADD_MEMBERSHIP on every group you want to receive datagram from.
  6. 在要从其接收数据报的每个组上使用IP_ADD_MEMBERSHIP setockopt。

  7. 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)
  8. 在我看来,使用IP_PKTINFO提供了区分收到的数据包的选项,但发送者必须注意准备它们(设置UDP套接字的源IP)

#6


-3  

I do not believe it possible to join more than one multicast group on a given socket. The socket is defined by the pairing of the source ip/port and destination ip/port. The operating system would not know what to do with data that comes down from the second ip/port because it would not have a socket to send it to.

我不相信可以在给定套接字上加入多个多播组。套接字由源IP /端口和目标IP /端口的配对定义。操作系统不知道如何处理来自第二个ip / port的数据,因为它没有套接字来发送它。

The bind is necessary to register the connection with the operating system. It's basically like registering a file handle.

绑定是注册与操作系统的连接所必需的。它基本上就像注册文件句柄一样。

The best way to do this would be to create a socket for each multicast group and then call select(). select() will inform you if any socket has data ready for reading.

执行此操作的最佳方法是为每个多播组创建一个套接字,然后调用select()。如果任何套接字已准备好读取数据,select()将通知您。

Check your man pages for more info on socket(), bind(), and select().

有关socket(),bind()和select()的更多信息,请查看手册页。