【问题标题】:C++ receiving multicast on particular interfaceC++ 在特定接口上接收多播
【发布时间】:2018-02-05 14:13:33
【问题描述】:

IP_ADD_MEMBERSHIP 上的文档说:

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

      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.

所以我有一个 ip 为 192.168.1.5 的接口“eth0”。我想将此接口加入多播组 225.1.1.1。我对如何正确设置 ip_mreqn 结构有点困惑?我找到了两种可能的方法:

1.

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;

2.

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

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

我的问题是。

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

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

3) 选项 SO_BINDTODEVICE 有什么用处?

编辑:我做了一些研究。

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

这些方式工作正常(我在 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");

甚至

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

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

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

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

【问题讨论】:

    标签: c++ c network-programming multicast


    【解决方案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");
    

    【讨论】:

    • 感谢您的评论。这是我的 B 计划。
    【解决方案2】:

    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首先用于搜索设备。如果发现NOT,则使用imr->imr_address

    【讨论】:

      猜你喜欢
      • 2012-11-30
      • 2011-04-17
      • 1970-01-01
      • 1970-01-01
      • 2015-04-03
      • 1970-01-01
      • 2021-07-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多