组播和广播有什么不同?加入一个组播组时线上发生了什么?组播的 TTL 为什么默认是 1,环回是怎么回事?这篇在本机 en0 和 lo0 上真的加入一个组,抓 IGMP 报告和组播帧,逐项验证成员关系、TTL 范围、回环和接口的规则。
加入前 netstat -g 里 en0 的 IPv4 组 2 个(没有 239.255.42.99);加入后:['239.255.42.99', '1:0:5e:7f:2a:63', 'en0'] 239.255.42.99 → 以太网组播 MAC = 01:00:5e + 低 23 位 = 01:00:5e:7f:2a:63(第二字节的最高位被清掉,只取 IP 地址后 23 位) 抓到 IGMP 报文:IP 目的 224.0.0.251,以太网目的 MAC 01:00:5e:00:00:fb,IGMP 类型 0x16(成员报告),组地址 224.0.0.251,IP 头 24 字节(含 Router Alert 选项),TTL 1 抓到 IGMP 报文:IP 目的 239.255.42.99,以太网目的 MAC 01:00:5e:7f:2a:63,IGMP 类型 0x16(成员报告),组地址 = 239.255.42.99,IP 头 24 字节(含 Router Alert 选项),TTL 1 抓到 IGMP 报文:IP 目的 224.0.0.251,以太网目的 MAC 01:00:5e:00:00:fb,IGMP 类型 0x16(成员报告),组地址 224.0.0.251,IP 头 24 字节(含 Router Alert 选项),TTL 1 共 3 个 IGMP 报文;32 个不同的组播 IP 地址会映射到同一个以太网 MAC(IP 地址里有 5 位被丢掉),例如 239.255.42.99 与 224.127.42.99 的 MAC 相同 验证:224.127.42.99 → 01:00:5e:7f:2a:63,与 239.255.42.99 的 MAC 相同
IP_ADD_MEMBERSHIP 让网卡开始收对应的以太网组播 MAC 的帧,同时内核发出 IGMP 成员报告。netstat -g 能看到成员关系和 MAC。
IP_MULTICAST_LOOP 默认值 1(1 = 本机上加入了组的套接字也会收到自己发的) 默认(LOOP=1):加入了组的接收方 1 收到;加入了组的接收方 2(同一端口,SO_REUSEPORT)收到;没有加入组、只绑了 0.0.0.0 端口的接收方 没收到 IP_MULTICAST_LOOP = 0:加入了组的接收方 1 没收到;接收方 2 没收到(同一台机器上的接收方都收不到了;别的机器仍然能收到,这里没有第二台机器可验证) 没有设置 IP_MULTICAST_IF 的发送方发同一个组:加入了组的接收方 1 收到(出口按路由表选) 线上:以太网目的 MAC 01:00:5e:7f:2a:63(= 组播 MAC 01:00:5e:7f:2a:63:True),IP 目的 239.255.42.99,TTL 1
只有加入了组的套接字收得到(包括同一台机器上的其它加入者);关掉 IP_MULTICAST_LOOP 后同一台机器上的接收方就收不到自己发的包。
新套接字 IP_MULTICAST_TTL 默认 = 1;设成 1 / 4 / 32 后线上抓到的 TTL:1 → [1];4 → [4];32 → [32] 传统约定:TTL 0 = 只在本机;1 = 本子网;<32 = 本站点 / 机构内;<64 = 本地区;<128 = 本大洲;<255 = 全球。组播路由器每转发一次 TTL 减 1,所以 TTL 同时是“传播半径”;本机默认 1,所以默认不会离开这个网段 224.0.0.0/24 是“本地链路”组播(路由器永远不转发),8 秒里抓到别的设备发往它的 IP 包 236 个,TTL 取值 [1, 254, 255]
默认 TTL 是 1,只在本网段;TTL 越大传播半径越大;224.0.0.0/24 永远是本地链路。
route get 239.255.42.99:接口 en0,标志 <UP,HOST,DONE,LLINFO,WASCLONED,MULTICAST,IFSCOPE> 接收方在某个接口地址上加入,发送方用同一个接口地址发:en0 的地址:收到;lo0 的地址 127.0.0.1:收到 接收方在 lo0 上加入、发送方从 en0 发:没收到——组播成员关系是按接口算的,在哪个接口加入就只收那个接口来的
成员关系属于接口:在 lo0 上加入就只收 lo0 来的组播,发送方用 IP_MULTICAST_IF 选出口。
一个套接字连续加入 400 个不同的组,全部成功 (sysctl 里没有 net.inet.ip.maxmemberships 这一项) 两个套接字加入同一个组 239.255.42.77:netstat 里该组的条目数 1;关掉第一个套接字后 1;关掉第二个后 0——内核对同一个接口上的同一个组只记一个成员,按引用计数,最后一个套接字离开才真正退出
同一个接口上的同一个组只记一条成员关系,按引用计数,最后一个套接字离开才真正退出。