when I created two udp sockets and I bind them to INADDR_ANY and same port number. but one of them joined a multicast group. but both of them can receive data from the same multicast group, even one of sockets didn't join to the multicast group.
2 回答
linux 内核不跟踪 IGMP 连接的状态。IGMP 是一种路由器协议。向多播组发送 IGMP 加入只是告诉路由器它应该将数据包转发到给定的地址和端口。请注意,路由器必须能够与 IGMP 通信。
这意味着尽管您曾经setsockopt()
加入多播组,但内核不会像您预期的那样跟踪每个套接字的成员资格。内核只是向路由器发送一个 IGMP 加入数据包。您可以使用wireshark 或其他方式验证这一点。
由于内核不跟踪套接字的 IGMP 状态,因此该地址和端口上的传入流量只是内核的“常规”流量。
因此,如果您将两个套接字绑定到相同的地址和端口,然后使用该地址和端口发送 IGMP 连接,则数据包在两个套接字上都可用是预期的行为。
BTW:为什么你需要两个套接字绑定到相同的地址和端口?
更新:根据@Ambroz Bizjak 的解释(谢谢),Linux 内核不跟踪 IGMP 连接状态的说法是不正确的。确实如此。但是,如果多个套接字绑定到相同的地址和端口,它不会使用此信息来决定哪些数据包应该转发到哪个套接字。
内核根本不会根据套接字所属的多播组来过滤传入的多播数据包。如果您不将套接字添加到组,如果同一系统上的其他套接字是成员,它可能仍会接收到组的多播。(我不确定如果多播到达但没有套接字是成员会发生什么。您可以测试是否愿意。)
请注意,内核实际上确实跟踪组所有权,甚至是每个套接字。它必须,否则无法正确实现 IGMP 协议的客户端。例如,内核需要回复来自路由器的各种 IGMP 查询(询问主机加入了哪些组),因此当没有更多套接字加入时,它知道发送离开组消息一个特定的群体。