如果我在关闭套接字之前不发送 IP_DROP_MEMBERSHIP 会怎样?
What happens if I don't send IP_DROP_MEMBERSHIP before closing my socket?
我正在编写一些使用 IGMP 加入来加入多播组的代码
struct ip_mreq mreq;
inet_pton(AF_INET, group, &mreq.imr_multiaddr.s_addr);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) < 0)
throw std::runtime_error(perror("setsockopt(IP_ADD_MEMBERSHIP)"));
当应用程序关闭时,它会关闭套接字
close(fd);
但是,它不会执行 IP_DROP_MEMBERSHIP
。
- 上游路由器会继续将多播传送到我的网络接口吗?
- OS(在我的例子中是 Linux)是否足够智能,可以在套接字关闭时为我发送删除成员资格请求?
是的,Linux 为它之前在特定接口上加入的每个多播组维护一个引用计数,并且当您关闭与请求特定组成员资格的套接字对应的最后一个文件描述符时,Linux 检查此组成员的引用计数是否为空,如果是,它将在相应的网络接口上发送类型为 'Leave group' 的成员报告。
只需按照以下步骤自行检查:
要么使用您的程序,要么使用 socat
请求特定的多播组成员资格。例如:
% socat STDIO UDP4-DATAGRAM:239.101.1.68:8889,ip-add-membership=239.0.1.68:192.168.250.2
(将 192.168.250.2 替换为您的其中一个接口的地址 - 请注意,在此示例中,具有此地址的接口名为 tun0
)
现在,查看您Linux节点上的多播组成员资格:
% netstat -gn
IPv6/IPv4 Group Memberships
Interface RefCnt Group
--------------- ------ ---------------------
lo 1 224.0.0.1
[...]
tun0 1 239.0.1.68
最后,嗅探你的网络接口:
# tshark -n -i tun0 -Y igmp
Running as user "root" and group "root". This could be dangerous.
Capturing on 'tun0'
现在,杀死 socat(例如 pkill socat
)。
您应该会看到由 tshark 编写的以下行:
7 2.197520 192.168.250.2 -> 224.0.0.22 IGMPv3 40 Membership Report / Leave group 239.0.1.68
此外,您可以尝试同时启动您的程序的多个实例,您会看到只有当您杀死最新的实例时,才会发送 Leave group
消息。您还将看到 运行 程序的实例数是出现在 netstat -gn
.
第二列输出中的数字
Will multicast continue to be delivered to my network interface by the upstream router?
除非您的主机中还有其他群组成员。
Is the OS (in my case Linux) smart enough to send the drop membership request for me when the socket is closed?
是的。你不需要担心 IP_DROP_MEMBERSHIP 除非你想在套接字上动态更改组,这是非常罕见的:我当然从来没有做过。
我正在编写一些使用 IGMP 加入来加入多播组的代码
struct ip_mreq mreq;
inet_pton(AF_INET, group, &mreq.imr_multiaddr.s_addr);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) < 0)
throw std::runtime_error(perror("setsockopt(IP_ADD_MEMBERSHIP)"));
当应用程序关闭时,它会关闭套接字
close(fd);
但是,它不会执行 IP_DROP_MEMBERSHIP
。
- 上游路由器会继续将多播传送到我的网络接口吗?
- OS(在我的例子中是 Linux)是否足够智能,可以在套接字关闭时为我发送删除成员资格请求?
是的,Linux 为它之前在特定接口上加入的每个多播组维护一个引用计数,并且当您关闭与请求特定组成员资格的套接字对应的最后一个文件描述符时,Linux 检查此组成员的引用计数是否为空,如果是,它将在相应的网络接口上发送类型为 'Leave group' 的成员报告。
只需按照以下步骤自行检查:
要么使用您的程序,要么使用
socat
请求特定的多播组成员资格。例如:% socat STDIO UDP4-DATAGRAM:239.101.1.68:8889,ip-add-membership=239.0.1.68:192.168.250.2
(将 192.168.250.2 替换为您的其中一个接口的地址 - 请注意,在此示例中,具有此地址的接口名为
tun0
)现在,查看您Linux节点上的多播组成员资格:
% netstat -gn IPv6/IPv4 Group Memberships Interface RefCnt Group --------------- ------ --------------------- lo 1 224.0.0.1 [...] tun0 1 239.0.1.68
最后,嗅探你的网络接口:
# tshark -n -i tun0 -Y igmp Running as user "root" and group "root". This could be dangerous. Capturing on 'tun0'
现在,杀死 socat(例如
pkill socat
)。 您应该会看到由 tshark 编写的以下行:7 2.197520 192.168.250.2 -> 224.0.0.22 IGMPv3 40 Membership Report / Leave group 239.0.1.68
此外,您可以尝试同时启动您的程序的多个实例,您会看到只有当您杀死最新的实例时,才会发送 Leave group
消息。您还将看到 运行 程序的实例数是出现在 netstat -gn
.
Will multicast continue to be delivered to my network interface by the upstream router?
除非您的主机中还有其他群组成员。
Is the OS (in my case Linux) smart enough to send the drop membership request for me when the socket is closed?
是的。你不需要担心 IP_DROP_MEMBERSHIP 除非你想在套接字上动态更改组,这是非常罕见的:我当然从来没有做过。