【问题标题】:IP_DROP_MEMBERSHIP behaviour inconsistencyIP_DROP_MEMBERSHIP 行为不一致
【发布时间】:2018-10-26 04:33:56
【问题描述】:
我有一个用例,我使用 IP_ADD_MEMBERSHIP 加入会员资格,一段时间后我必须使用 IP_DROP_MEMBERSHIP(就在 drop seq id 为 1 之前),然后我再次使用 IP_ADD_MEMBERSHIP 加入会员资格(对于同一个多播组)。我注意到我收到了我认为不应该发生的下一个数据包(seqid = 2),因为根据我的理解 IP_DROP_MEMBERSHIP 应该停止接收 udp 数据包并刷新它正在使用的套接字,一旦我加入它应该是可用的最新数据包和这种行为不一致有时我只得到最新的数据包。
请注意,我不想关闭套接字。继续使用现有的。
请帮忙。我正在使用 Centos 7.4
【问题讨论】:
标签:
c
networking
network-programming
udp
multicast
【解决方案1】:
尝试将 IP_MULTICAST_ALL 设置为 0。默认为 1。
说明:使用 IP_MULTICAST_ALL 0,您的操作系统将过滤传入的 UDP 数据包到您当前加入的组,这正是您在描述中所期望的。
但这不是 Linux 上的默认行为。
默认(IP_MULTICAST_ALL=1)是接收进入您的套接字的任何个UDP数据包。当您绑定到 0.0.0.0 时,这将是机器为该端口接收的所有 UDP 数据包,多播和单播,无论您是否加入任何多播组。这意味着您将看到加入和离开多播组之间差异的所有工件以及您的机器发送的实际 IGMP 消息,您还将看到本地网络中所有路由器和交换机的所有工件和错误。例如,当您离开多播组时,您的操作系统可能决定根本不发送相应的 IGMP 消息,例如因为其他一些套接字也在侦听该多播地址,或者因为操作系统决定延迟离开。这都是完全允许的。
顺便说一句,当你在Linux上绑定多播地址时,这只是一个过滤功能,根本没有绑定功能。然后,您将只接收针对该特定多播 IP 的 UDP 数据包,无论您是否也加入了其他多播组。
关于“刷新”套接字:套接字后面的数据包队列完全超出了您的应用程序的范围。您不能影响队列状态或行为(除了是否从队列中读取),也不能期望任何特定行为。
在实践中,我建议:
- 绑定到 0.0.0.0。
- 适当地加入和离开多播组。
- 检查您收到的每个 UDP 数据包的目标地址并自己进行任何过滤。使用 IP_PKTINFO 获取每个数据包的目标地址。
- 完全不要依赖具有任何明显和确定性多播路由行为的路由器和交换机。他们中的大多数人在离开多播组时都有很长的超时时间。这意味着即使您离开了多播组(即使您没有加入),您也可能会在几分钟内继续接收多播流量。这会掩盖代码中的错误,并且在尝试调试时会让人头疼。
这样您就不必依赖任何依赖于操作系统的行为,并且您可以完全控制收到的内容和不收到的内容。