c - IP_DROP_MEMBERSHIP 行为不一致

标签 c networking network-programming udp multicast

我有一个用例,其中我使用 IP_ADD_MEMBERSHIP 加入成员资格,一段时间后我必须使用 IP_DROP_MEMBERSHIP (就在 drop seq id 为 1 之前),然后再次使用 IP_ADD_MEMBERSHIP 加入成员资格(对于同一多播组)。我注意到我正在收到下一个数据包(seqid = 2),我认为这不应该发生,因为根据我的理解,IP_DROP_MEMBERSHIP 应该停止接收 udp 数据包并刷新它正在使用的套接字,一旦我加入回来,它应该是最新的数据包可用,并且这种行为不一致,有时我只得到最新的数据包。

请注意,我不想关闭套接字。继续使用现有的。

请帮忙。我使用的是Centos 7.4

最佳答案

尝试将 IP_MULTICAST_ALL 设置为 0。默认为 1。

说明:使用 IP_MULTICAST_ALL 0,您的操作系统将过滤传入您当前加入的组的 UDP 数据包,这正是您在描述中所期望的。

但这不是 Linux 上的默认行为。

默认(IP_MULTICAST_ALL=1)是接收进入套接字的任何 UDP 数据包。当您绑定(bind)到 0.0.0.0 时,这将是计算机为该端口接收的所有 UDP 数据包,多播和单播,无论您是否加入任何多播组。这意味着您将看到加入和离开多播组与您的计算机发送的实际 IGMP 消息之间的差异的所有工件,并且您还将看到本地网络中所有路由器和交换机的所有工件和错误。例如,当您离开多播组时,您的操作系统可能决定根本不发送相应的 IGMP 消息,例如因为其他某个套接字也在监听该多播地址,或者因为操作系统决定延迟离开。这都是完全允许的。

顺便说一句,当你在Linux上绑定(bind)多播地址时,这只是有过滤功能,根本没有绑定(bind)功能。然后,您将只收到针对该特定多播 IP 的 UDP 数据包,无论您是否也加入了其他多播组。

关于“刷新”套接字:套接字后面的数据包队列完全超出了您的应用程序的范围。您无法影响队列状态或行为(除了是否从队列中读取),也不能期望任何特定行为。

在实践中我建议: - 绑定(bind)到0.0.0.0。 - 适本地加入和离开多播组。 - 检查您收到的每个 UDP 数据包的目标地址并自行进行过滤。使用 IP_PKTINFO 获取每个数据包的目标地址。 - 完全不要依赖具有任何明显且确定性多播路由行为的路由器和交换机。他们中的大多数都有分钟长的超时时间来离开多播组。这意味着即使您离开多播组(甚至没有加入),您也可能会在几分钟内继续接收多播流量。这会掩盖代码中的错误,并且在尝试调试时会引起头痛。

这样您就不必依赖任何操作系统相关行为,并且可以完全控制您收到的内容和不收到的内容。

关于c - IP_DROP_MEMBERSHIP 行为不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53001477/

相关文章:

c++ - Cuda - 体系结构 x86_64 OS X 的 undefined symbol

c++ - 对 C++/分布式系统/网络项目的建议

Docker:在网络上强制内部容器通信

c - 在 unsigned int 中搜索位模式

c - RC522默认键

python - 如何保持Python服务器连接打开,直到客户端完成它?

unit-testing - 单元测试网络连接

C# 等待 TCP 响应的良好实践

c - 解析网络和解析文件之间有什么区别吗?

c++ - 已排序数组的一部分被反转