C ++在特定接口上接收多播

时间:2018-02-05 14:13:34

标签: c++ c network-programming multicast

关于IP_ADD_MEMBERSHIP的文档说:

  

IP_ADD_MEMBERSHIP(自Linux 1.2起)                加入组播组。参数是一个ip_mreqn结构。

var InsuranceVM = new Vue({
  delimiters: ['[[', ']]'],
  el: '#insurance-form',
  data: {
    insurance_types: [],
        insurance_type: '',
    insurance_types_get_error: '',
  },
  watch: {
        // whenever question changes, this function will run
        insurance_type: function (newQuestion, oldQuestion) {
              //this.answer = 'Waiting for you to stop typing...'

          this.getAnswer(newQuestion)
        }
      },
      methods: {
        getAnswer: _.debounce(
          function () {  
            var vm = this;
            axios.post('http://35.196.91.194/insurance-list', {})
              .then(function (response) {
                vm.insurance_types_get_error = '';

                vm.insurance_types = response.data.results;

              })
              .catch(function (error) {
                vm.insurance_types_get_error = 'Error! Could not reach the API. ' + error;
              })
          },
          500
        )
      }
});

所以我有一个界面" eth0"用ip 192.168.1.5。我想将此接口加入多播组225.1.1.1。我对如何正确设置ip_mreqn结构有点困惑?我发现了两种可能的方式:

1

      struct ip_mreqn {
          struct in_addr imr_multiaddr; /* IP multicast group
                                           address */
          struct in_addr imr_address;   /* IP address of local
                                           interface */
          int            imr_ifindex;   /* interface index */
      };

  imr_multiaddr contains the address of the multicast group the appli‐
  cation wants to join or leave.  It must be a valid multicast address
  (or setsockopt(2) fails with the error EINVAL).  imr_address is the
  address of the local interface with which the system should join the
  multicast group; if it is equal to INADDR_ANY, an appropriate inter‐
  face is chosen by the system.  imr_ifindex is the interface index of
  the interface that should join/leave the imr_multiaddr group, or 0 to
  indicate any interface.

2

ip_mreqn group;
group.imr_multiaddr.s_addr = inet_addr("225.1.1.1");
group.imr_address.s_addr = inet_addr("192.168.1.5");
group.imr_ifindex = 0;

第三种方法是使用SO_BINDTODEVICE套接字选项。

我的问题是。

1)将特定接口加入组播组的正确方法是什么?

2)imr_address和imr_ifindex之间的功能区别是什么?

3)SO_BINDTODEVICE选项如何有用?

编辑:我做了一些研究。

假设我有两个网络接口:eth0与ip 192.168.1.5和eth1与ip 192.168.1.255我在eth0上接收多播,ip 192.168.1.5。

这些方法正常工作(我在eth0上收到多播消息):

ip_mreqn group;
group.imr_multiaddr.s_addr = inet_addr("225.1.1.1");
group.imr_address.s_addr = htonl(INADDR_ANY);
group.imr_ifindex = if_nametoindex("eth0");

group.imr_address.s_addr = inet_addr("192.168.1.5");
group.imr_ifindex = 0;

或显然

group.imr_address.s_addr = htonl(INADDR_ANY);
group.imr_ifindex = if_nametoindex("eth0");

甚至

group.imr_address.s_addr = inet_addr("192.168.1.5");
group.imr_ifindex = if_nametoindex("eth0");

这些方式(我不会在eth0上收到多播消息):

group.imr_address.s_addr = inet_addr("192.168.1.255");
group.imr_ifindex = if_nametoindex("eth0");

group.imr_address.s_addr = inet_addr("192.168.1.5");
group.imr_ifindex = if_nametoindex("eth1");

2 个答案:

答案 0 :(得分:1)

我一直使用较早的struct ip_mreq代替struct ip_mreqn,因为两者都受支持。这个结构没有索引字段,因此它对于你需要设置的内容不那么模糊。

struct ip_mreq
  {
    /* IP multicast address of group.  */
    struct in_addr imr_multiaddr;

    /* Local IP address of interface.  */
    struct in_addr imr_interface;
  };

然后你会这样设置:

struct ip_mreq group;
group.imr_multiaddr.s_addr = inet_addr("225.1.1.1");
group.imr_interface.s_addr = inet_addr("192.168.1.5");

答案 1 :(得分:0)

ip_mreqn 用于在 linux/net/ipv4/igmp.c(linux 5.13) 的内核源代码中查找网络接口设备,如下所示。

static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr)
{
    struct net_device *dev = NULL;
    struct in_device *idev = NULL;

    if (imr->imr_ifindex) {
        idev = inetdev_by_index(net, imr->imr_ifindex);
        return idev;
    }
    if (imr->imr_address.s_addr) {
        dev = __ip_dev_find(net, imr->imr_address.s_addr, false);
        if (!dev)
            return NULL;
    }

    if (!dev) {
        struct rtable *rt = ip_route_output(net,
                            imr->imr_multiaddr.s_addr,
                            0, 0, 0);
        if (!IS_ERR(rt)) {
            dev = rt->dst.dev;
            ip_rt_put(rt);
        }
    }
    if (dev) {
        imr->imr_ifindex = dev->ifindex;
        idev = __in_dev_get_rtnl(dev);
    }
    return idev;
}

imr->imr_ifindex 首先用于搜索设备。如果未找到,则使用 imr->imr_address