基础概念
在现代网络环境中,组播(Multicast) 和 广播(Broadcast) 技术被广泛用于需要与多个主机进行通信的应用场景,尤其在企业和本地网络(LAN)中比在广域网(WAN)中更为常见。尽管组播的设计初衷包括支持广域组播通信,但由于广域组播路由协议实现复杂,因此实际部署主要集中在局域网中。
广播
广播(Broadcast)是指将数据报文发送至网络中所有可能的接收者。在原理上,它较为简单:路由器或主机将报文副本发送到除输入接口外的所有接口。
链路层支持的广播机制
以太网每帧都包含源 MAC 和目的 MAC 地址。正常情况下使用单播地址,仅目标主机接收。但在广播场景中,目的地址使用特殊的广播地址:
广播 MAC 地址:ff:ff:ff:ff:ff:ff
,表示同一网段内的所有主机
类型 | MAC 地址示例 | 说明 |
---|---|---|
单播地址 | 00:1A:2B:3C:4D:5E | 定向至特定设备 |
组播地址 | 01:00:5e:xx:xx:xx | 定向至一个多主机的组 |
广播地址 | ff:ff:ff:ff:ff:ff | 定向至网段内所有主机 |
应用层发送广播数据报
广播通常配合 UDP 协议 使用,因为 UDP 是无连接的,适合一对多的通信。典型应用包括:ARP 请求,DHCP 地址请求,本地服务发现。
🚫 广播不适合 TCP,因为 TCP 要求建立连接,而广播目的不唯一,无法完成握手过程。
$ ping 10.0.0.255
Do you want to ping broadcast? Then -b
Linux 默认禁止广播,除非添加 -b 参数。这是为了避免误发广播造成网络拥塞。
开启广播的 Socket 设置(C 示例):
int sock = socket(AF_INET, SOCK_DGRAM, 0);
int broadcastEnable = 1;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));
组播
组播的基本思想是:只将数据发送给感兴趣的主机,从而避免不必要的数据传输和处理开销。这种兴趣可以通过以下两种方式建立:
- 发送方控制模型:发送者指定目标接收组。
- 接收方控制模型:接收者通过协议主动声明它对某个组感兴趣(IP组播采用此方式)。
将IP组播地址转换为802MAC/以太网地址
在支持广播或组播的链路层网络(如以太网或 Wi-Fi)中,IP 层的组播地址必须映射为对应的链路层 MAC 地址,以便正确封装和传输数据。与单播地址需要 ARP(IPv4)或 ND(IPv6)解析不同,组播地址使用一种规则映射机制直接计算出 MAC 地址。
- IPv4 组播地址范围:
224.0.0.0
~239.255.255.255
- MAC 地址映射前缀:
01:00:5e
- 使用 IPv4 地址的 低 23 位 进行映射(MAC 地址后 3 个字节)
IPv6 组播地址映射到 MAC 地址
- IPv6 组播地址范围:
ff00::/8
- MAC 地址映射前缀:
33:33
- 使用 IPv6 地址的 最低 32 位 映射到 MAC 地址的后两字节
这种映射机制允许链路层设备(如交换机)基于组播 MAC 地址过滤与转发数据帧,从而实现有效的多播帧传递,而不影响未订阅的主机。
发送组播数据报
组播通信依赖主机对组播组的动态加入与离开。发送端根据本地路由选择接口,接收端根据接口和应用程序的声明决定是否接收数据。
在发送组播时,系统需选择一个适当的网络接口作为出接口。这个选择通常遵循系统的路由表。例如,Linux 中可通过 ip route
查看,Windows 中可通过 route print
或 netstat -rn
查看。
接收组播数据报
组播的接收侧由操作系统根据应用程序加入的组播组动态维护。主机必须在特定接口上**“加入”组播组**才能接收相关流量。
主机地址过滤
为了让操作系统能够将接收到的组播数据报正确交付给应用程序,主机必须在多个层级上完成对数据报的地址过滤。这些过滤操作从网络接口卡(NIC)开始,一直到UDP或TCP层的端口过滤。
在典型以太网中,广播与组播帧都会通过交换机生成树复制到所有 VLAN 成员主机。NIC 必须决定是否“接收”这些帧。NIC 对组播的处理方式主要有两类:
-
散列过滤(Hash-Based Filtering)
- 对组播 MAC 地址做哈希;
- 哈希结果映射到一个比特向量;
- 若对应位置为
1
,则接收该帧; - ⚠️ 有可能误接收冲突帧(误报);
- 性能较高但不完全精确。
-
地址表匹配(Exact Match Filtering)
- NIC 维护一个可配置的地址表(如 16 项);
- 只接收表中明确列出的组播 MAC 地址;
- 若组数超限,进入“组播混杂模式”,接收所有组播帧;
- 性能稳定但表容量有限。
在数据帧通过 NIC 确认有效后,进入驱动程序和协议栈:
-
驱动层过滤
- 检查帧类型(如 IPv4、IPv6、ARP);
- 判断是否是支持的协议;
- 进一步过滤非法或不相关的组播数据。
-
IP 层过滤
- 匹配目标 IP 是否是主机加入的组播组;
- 对于误报帧(如哈希冲突),在此处被丢弃;
- 若匹配,则向上传递给传输层。
UDP 再次基于端口进行过滤:
- 若没有进程绑定该目的端口:
- 丢弃数据报;
- 生成 ICMP 端口不可达 报文;
- 若有绑定:
- 若校验和正确,则交给应用程序;
- 若校验和错误,则直接丢弃。
互联网组管理协议和组播侦听发现协议
当组播通信跨越多个子网或在广域网(WAN)中进行传递时,仅依靠链路层或局部广播的方式已经不再适用。这时,必须由一个或多个“组播路由器”(Multicast Router)承担跨网络转发和组成员发现的任务。
在进行组播数据转发时,路由器并非像单播那样基于目的地址查路由,而是:
- 根据源地址反向查路由表;
- 判断数据报是否来自“最短路径”;
- 只有数据报来自路由器前往源地址的最佳接口时,才允许转发;
- 可有效避免组播环路(Loop)。
组播路由器必须了解——在其每个接口上有哪些主机对哪些组播组感兴趣。
- IPv4:IGMP(Internet Group Management Protocol)
- IPv6:MLD(Multicast Listener Discovery)
组成员的IGMP和MLD处理(“组成员部分”)
IGMP 和 MLD 的组成员部分允许主机指定感兴趣的组播地址,并指示是否接收来自特定源的流量。主机通过向本地子网内的组播路由器发送报告报文,来表达其接收意图。报告可以是对查询报文的响应,也可以是由于本地状态变化(如应用加入/离组)而主动发送的。
IGMPv3 的报告报文格式如下:
每个 Group Record 包括以下信息:
- 类型(Type)
- 组播地址(Multicast Address)
- 源地址列表(可为空)
- 可选的辅助数据(IGMPv3 中未使用)
组播路由器的IGMP和MLD处理(“组播路由器部分”)
组播路由器负责根据收到的成员报告和发送的查询,维持每个接口上每个组播组与源的接收状态。该状态为软状态,若长时间未刷新,则会被系统清除。
IGMPv3 查询报文格式:
- 类型:0x11,表示 IGMP 查询
- 最大响应代码(MaxRespCode):控制主机在回应前的最大延迟
- QRV:QuerierRobustness Variable,表示最大重传次数
- QQIC:Querier’s Query IntervalCode,表示查询间隔(单位为秒)
- 组播地址:可以为具体组播地址,也可以为 0 表示通用查询
- 源地址列表:可选,用于组/源特定查询
MaxRespCode 字段的编码
- 当 MaxRespCode <= 127 时,值直接以 100ms 为单位。
- 当 MaxRespCode > 127 时,采用如下编码格式:
查询类型 | 描述 | 目的地址 |
---|---|---|
一般查询 | 查询所有组的成员状态 | 224.0.0.1 / ff02::1 |
特定组查询 | 查询某个特定组的成员状态 | 该组组播地址 |
组+源查询 | 查询某个组及其特定源是否还有成员 | 该组组播地址 |
查询行为说明
- 一般查询:用于刷新所有组的状态。
- 特定组查询:仅查询某一组的状态。
- 组+源查询:判断对特定源是否还有成员。
组播路由器会根据收到的“过滤器模式变更”或“源列表变更”报告,发送特定查询验证状态。若没有成员响应,便终止该组或源的数据转发。
轻量级IGMPv3 和 MLDv2
主机维护与其应用程序和系统软件感兴趣的组播组及源地址的过滤器状态。在 IGMPv3 / MLDv2 中,主机还可以指定“包含”或“排除”的源列表。相应地,组播路由器也维护每个组及其源的状态,以决定是否需要将组播流量转发到链路上。
尽管协议支持排除源的复杂功能,但实践中应用程序很少这样使用。反而,更多的应用关注于“仅接收特定源”的能力,尤其在使用 SSM(Source-Specific Multicast)时。因此,为简化实现,[RFC5790] 提出了:
- LW-IGMPv3(Lightweight IGMPv3)
- LW-MLDv2(Lightweight MLDv2)
它们是 IGMPv3 和 MLDv2 的功能子集,支持 ASM(Any-Source Multicast)与 SSM,使用与完整版本相兼容的报文格式,但省去了对特定源的排除功能。
IGMP 和 MLD 健壮性
IGMP 和 MLD 协议的失效或组播机制的故障,可能导致以下两种结果:
- 向不需要的主机分发组播流量;
- 无法向需要的主机交付期望的组播流量。
为解决路由器失效的问题,允许多个组播路由器在同一链路中协同工作。其中,具有最小 IP 地址的路由器会被选为“查询器(Querier)”,负责周期性地发送一般和特定查询,获取子网中主机的组播状态。其他路由器则作为“非查询器”,监听查询器发出的报文并维持备用状态。一旦当前查询器失效,备用路由器将在超时后接替角色,保障协议持续运作。
查询器选举机制是 IGMP 和 MLD 健壮性的重要组成部分。每个路由器初始认为自己是查询器,当监听到其他查询器报文后会根据源 IP 比较做出角色切换,确保子网中仅有一个查询器在正常发送报文。所有路由器统一采用查询器配置的查询间隔和参数,使切换时系统行为稳定。
查询器会以固定间隔发送“通用查询”探测所有组,也会发送“特定组”或“特定组和源”查询来确认某个组或源是否仍有主机感兴趣。当某主机离组时,查询器会使用较短的“最后成员查询时间(LMQT)”发送高频特定查询,以快速收敛组播转发状态。为避免丢包引起的误判,这些查询会根据“QRV(Querier Robustness Variable)”字段设置重传次数。
报文丢失通过报文重传来缓解。状态变化报告和特定查询是需要重传的重要类型,而当前状态报告一般不重传,因为它们只用于刷新软状态。查询和报告重传的间隔具有一定的随机性(如报告在 0 与“主动报告间隔”之间随机,查询则基于 LMQT 周期发送),以防网络拥堵造成的同步冲突。
特定查询报文中引入的 S 位(Suppress)用于协调多个路由器计时器行为。首次特定查询发送时 S 位未置位,允许接收路由器缩短超时;后续重传时 S 位被置位,抑制非查询器将计时器再次降低,以防报文重复或遗漏带来的不一致。
尽管某个路由器已经收到合法的报告,系统仍会继续完成查询重传流程。这是为了确保所有路由器的状态超时保持一致,即使有报文丢失或非查询器未及时同步初始状态,也不会造成误判。S 位机制确保非查询器不会被重复查询误导,从而提升整体系统的健壮性。
IGMP 和 MLD 计数器和变量
IGMP和MLD是软状态的协议,它们也处理路由器的失效、协议报文的丢失以及与早期协议版本的互操作性。很多设备是基于触发状态改变和协议动作的计时器来启用这些功能的。
IGMP 和 MLD 探听
IGMP 和 MLD 协议管理 IP 组播在路由器间的流动。为了进一步优化第 2 层(数据链路层)设备上的组播流量转发,许多二层交换机实现了 IGMP/MLD 探听(snooping) 功能。该功能允许交换机侦听第 3 层的 IGMP/MLD 报文,从而判断特定端口是否对某个组播组感兴趣。
- 如果未启用 IGMP snooping,交换机会将所有组播流量泛洪到 VLAN 的所有端口,造成网络带宽浪费。
- 启用 IGMP snooping 后,交换机能够识别哪些端口需要接收哪些组播流量,避免了无效转发。
在 IGMPv1/v2 和 MLDv1 中:
- 主机报告(membership report)具有“抑制机制”:若主机在监听到其他主机已发送报告时,会取消自身报告。
- 若交换机将报告转发到所有端口,其他主机可能会抑制应答,导致报告无法完整传播。
- 解决方案:仅将报告转发至已知的组播路由器端口,避免对组播成员端口造成干扰。
若交换机实现了 组播路由器发现(MRD)协议,则可以自动识别哪些端口连接了组播路由器,更准确地将报告消息转发给需要的路由器端口。
IGMP 是独立协议(在 IPv4 中),MLD 是 ICMPv6 的一部分,与其他 ICMPv6 功能(如邻居发现)共用协议号。因此,MLD 探听交换机必须区分 ICMPv6 中的 MLD 报文与其他类型(如 Router Advertisement),避免错误处理或屏蔽正常 IPv6 功能。