【问题标题】:Receiving multicast on linux host with multiple interfaces在具有多个接口的 linux 主机上接收多播
【发布时间】:2018-01-17 20:18:46
【问题描述】:

我有一台运行 Ubuntu 16.04 的主机通过主有线网络接口连接到一个网络,并通过 USB 到以太网适配器连接到另一个网络。使用tcpdump,我能够验证两个网络接口上的传入多播数据包。但是,我的应用程序没有从辅助接口接收任何多播数据。如果我断开与主接口的电缆,然后重新启动我的应用程序,那么我确实会从辅助接口接收数据。只有两个接口都连接,应用程序才不会从辅助接口接收。

【问题讨论】:

  • 您已经通过多宿主主机中的每个接口依次迭代发出 JOIN 的接口。
  • @EJP 感谢您的指点。这解决了我的问题!

标签: c++ c linux networking multicast


【解决方案1】:

我发现了一个类似的问题(带有 USB 转以太网适配器的 Raspberry Pi Zero 无法响应 mDNS 查询)。要确定您的问题是否相同,您的应用程序是否在同时运行 tcpdump 时正确接收多播流量?使用--no-promiscuous-mode 运行 tcpdump 是否看不到多播流量?

如果您对两者的回答都是肯定的,那么我发现的解决方法就是ip link set eth0 promisc on。我不知道这是硬件错误(我使用的是 Kontron DM9601 适配器,ID 0FE6:9700)还是驱动程序错误,但无论哪种方式,启用混杂模式似乎都可以为我修复多播接收。或者,您可以尝试使用更好的 USB 转以太网适配器。

【讨论】:

  • 谢谢!我有相同的 DM9601 适配器,此更改解决了 pi 无法响应 mDNS 查找的问题。
【解决方案2】:

ip_mreq 结构作为IP_ADD_MEMBERSHIP 套接字选项的选项值传递以加入多播组。来自 Linux 文档项目的Multicast programming HOWTO

第一个成员imr_multiaddr 持有您要加入的群组地址。请记住,成员资格也与接口相关联,而不仅仅是组。这就是您必须为第二个成员提供值的原因:imr_interface。这样,如果您在多宿主主机中,您可以在多个接口中加入同一个组。您始终可以使用通配符地址 (INADDR_ANY) 填充最后一个成员,然后内核将处理选择接口的任务。

IP_MULTICAT_IF 套接字选项也与多宿主主机相关,用于为通过套接字发送的多播数据设置出站接口。有关这些套接字选项、ip_mreq 结构和较新的ip_mreqn 结构的更多信息,请参见here

对于在多宿主主机上使用 Boost 的用户,您需要使用本机句柄在特定接口上加入组。从在 Ubuntu 16.04 上运行的 Boost 1.58 开始,套接字选项抽象 ip::multiast::join_group() 在内核选择的接口上加入组,并且不允许开发人员指定接口。套接字选项抽象ip::multicast::outbound_interface() 控制出站接口,但不影响套接字在哪个接口上接收。

这是一个基于本地接口 IP 地址在特定接口上加入组的代码示例:

struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(discovery_ip);
mreq.imr_interface.s_addr = inet_addr(local_interface_ip);
if(setsockopt(socket_.native_handle(), IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) {
    ... handle error ...
}

【讨论】:

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