套接字没有加入多播组,但它可以接收数据。

Posted

技术标签:

【中文标题】套接字没有加入多播组,但它可以接收数据。【英文标题】:A socket didn't join a multicast group but it can receive data. 【发布时间】:2012-12-16 14:35:16 【问题描述】:

当我创建两个 udp 套接字并将它们绑定到 INADDR_ANY 和相同的端口号时。 但其中一个加入了多播组。 但是它们都可以从同一个多播组接收数据,即使其中一个套接字没有加入多播组。

【问题讨论】:

@Michael 阅读了socket man page 并搜索 SO_REUSEADDR @Micheal 在将 SO_REUSEADDR 与 UDP 一起使用时,它允许将多个套接字绑定到相同的地址和端口。 read。但是在阅读了这个帖子之后,我会说这更像是一种附带行为。最好将您指向SO_REUSEPORT @Michael 如果您不知道 SO_REUSEADDR 是做什么的,那么您根本不应该发布关于端口重用的主题。 TIME_WAIT 是一个 TCP 状态,这是一个 UDP 问题。您链接到的引文几乎不是权威来源。 【参考方案1】:

内核根本不会根据套接字所属的多播组来过滤传入的多播数据包。如果您不将套接字添加到组,如果同一系统上的其他套接字是成员,它仍可能接收到组的多播。 (我不确定如果多播到达但 no 套接字是成员会发生什么。你可以测试一下。)

请注意,内核实际上确实跟踪组所有权,甚至是每个套接字。它必须,否则无法正确实现 IGMP 协议的客户端。例如,内核需要回复来自路由器的各种 IGMP 查询(询问主机加入了哪些组),因此它也知道在没有更多套接字加入时发送离开组消息一个特定的群体。

【讨论】:

【参考方案2】:

Linux 内核不跟踪 IGMP 连接的状态。 IGMP 是一种路由器协议。向多播组发送 IGMP 加入只是告诉路由器它应该将数据包转发到给定的地址和端口。请注意,路由器必须能够与 IGMP 通信。

这意味着尽管您使用setsockopt() 加入多播组,但内核并未像您预期的那样跟踪每个套接字的成员资格。内核只是向路由器发送一个 IGMP 加入数据包。您可以使用wireshark 或其他方式验证这一点。

由于内核不跟踪套接字的 IGMP 状态,因此该地址和端口上的传入流量只是内核的“常规”流量。

因此,如果您将两个套接字绑定到相同的地址和端口,然后使用该地址和端口发送 IGMP 连接,则数据包在两个套接字上都可用是预期的行为。

顺便说一句:为什么需要将两个套接字绑定到相同的地址和端口?

更新:根据@Ambroz Bizjak 的解释(谢谢),Linux 内核不跟踪 IGMP 连接状态的说法是不正确的。确实如此。但是,如果多个套接字绑定到相同的地址和端口,它不会使用这些信息来决定哪些数据包应该转发到哪个套接字。

【讨论】:

这是不正确的。内核确实跟踪每个套接字的 IGMP 连接状态。它必须这样做,这样它才能正确实现 IGMP 协议(​​例如,响应 IGMP 通用查询和 IGMP 组特定查询)。但是它使用此信息来过滤传入的数据包。 以及为什么它需要跟踪 per-socket 您可能会问。因此,当最后一个加入特定组的套接字关闭时,它可以发送 IGMP 离开组消息,并停止回复对该组的查询。 @Ambroz Bizjak 哎呀。我不知道那件事。你应该回答这个问题。 @AmbrozBizjak 这一切都很好,但这里的证据是它在传递多播时不使用该信息。 @EJP 这不正是我在第一条评论中所说的吗? “但是它不使用这些信息来过滤传入的数据包。”我只是在纠正这个错误地声称“Linux 内核不跟踪 IGMP 连接状态”的答案。

以上是关于套接字没有加入多播组,但它可以接收数据。的主要内容,如果未能解决你的问题,请参考以下文章

多播组客户端不从服务器接收消息

Windows Phone 8 上的 UDP 多播组

使用 Windows 进行多播

TCP/IP详解 笔记九

网络编程之多播

Java 多播发送数据,不接收