序
在网络编程和系统开发中,我们习惯了"一对一"的单播通信。但当面对视频直播、行情分发或集群心跳检测时,单播的带宽消耗和服务器负载往往会成为瓶颈。
这时候,组播就成了那个"优雅"的解决方案。
很多开发者对组播的理解停留在"一对多"的概念上。今天,我们将剥开协议的洋葱,从报文结构、网卡驱动以及路由转发这三个底层视角,彻底看透组播到底是如何工作的。
1、报文的伪装:它其实和单播长得很像
如果我们用 Wireshark 抓包,你会发现一个有趣的事实:组播数据包的结构,和单播数据包几乎一模一样。
它们并没有一种特殊的"组播协议头",区别仅仅在于地址字段的数值不同。
- IP层:D 类地址的魔力
- 单播包的目的 IP 是具体的某台机器(如 192.168.1.100)。而组播包的目的 IP,使用的是 D类地址(范围 224.0.0.0 ~ 239.255.255.255)。这个 IP 地址不再代表"我是谁",而是代表"我要去哪个组"。
- 链路层:特殊的 MAC 映射
- 以太网帧如何知道这是组播包?看目的 MAC 地址。
- 单播 MAC:第一字节的最后一位是 0。
- 组播 MAC:第一字节的最后一位是 1。
- 在 IPv4 中,IANA 规定组播 MAC 地址的前 24 位固定为 01:00:5e,第 25 位为 0,后 23 位由组播 IP 地址的后 23 位映射而来。
注意:
由于 IP 地址有 28 位有效位(去掉前 4 位),而 MAC 地址只映射了 23 位,这意味着有 32 个组播 IP 会映射到同一个 MAC 地址上。这就是所谓的"哈希冲突"。这也解释了为什么网卡收到包后,协议栈还需要再做一次 IP 过滤。
2、驱动的视角:硬件过滤与软件过滤
作为一个熟悉驱动开发的工程师,你可能会问:"网卡是怎么处理这些包的?CPU 会因此过载吗?"这就涉及到了双重过滤机制。
-
发送端:只管发,别回头
- 发送端主机 A 在构造数据包时,源 IP/MAC 填自己,目的 IP/MAC 填组播地址。
- 最关键的是,发送端不需要知道接收端是谁。它不需要像单播那样去查 ARP 表获取对方的 MAC,也不需要建立连接。它就像对着山谷 喊话,把包往网线上一扔,任务就结束了。
-
接收端:网卡的哈希表
- 当组播包到达接收端主机 B 时,网卡硬件首先介入:
- 识别组播:网卡发现目的 MAC 的第一字节最后一位是 1,判定为组播包。
- 哈希匹配:驱动程序之前已经通过
setsockopt等接口,配置了网卡的多播哈希表。网卡计算该 MAC 地址的哈希值,如果命中表项,DMA 引擎才会把数据搬运到内存;否则直接丢弃 - 注意:由于前面提到的 32:1 映射冲突,网卡有时候会"误收"一些不属于本机的组播包(伪组播)。
- 当组播包到达接收端主机 B 时,网卡硬件首先介入:
-
协议栈:最后的把关
- 数据包上传到内核协议栈后,软件会进行第二次过滤:
- 检查包的目的 IP。
- 对比内核维护的组播组订阅列表。
- 只有 IP 也匹配,数据才会被交付给上层 Socket。
2.1 案例
某网卡控制器中,与组播相关的寄存器如下:
精确过滤:

逻辑:
- 驱动层把需要接收的组播 MAC 地址直接填入 MAC 地址寄存器中
- 当网卡收到该组播 MAC 地址的包后,就会把包送往协议栈
哈希过滤:

逻辑:
- 驱动层把组播 MAC 地址通过哈希算法算出一个索引值(比如第 5 位)
- 把寄存器里的第 5 位置 1
- 收到包时,网卡硬件自动算出该包 MAC 的哈希值,去查对应的位是不是 1
- 如果是 1 ,就把包送往协议栈
注意:以上组播的过滤方法,实际上对于单播也同样适用。MAC 控制器中,对于组播和单播的过滤方法,可以手动去选择控制。


3、 网络的视角:从"复制报文"到"复制路径"
如果仅仅是地址不同,那组播也没什么了不起。组播真正的威力在于路由器 和交换机的行为。
- 单播的噩梦
- 假设你要给 100 个客户端发 10MB 的视频:
- 服务器要发 100 次,消耗 100 份 CPU 和带宽
- 核心链路要跑 100 份数据流
- 组播的智慧:组播分发树。在组播网络中,路由器运行 PIM 等路由协议,构建一棵组播分发树
- 源头:服务器只发 1 份数据
- 主干:网络核心链路只传输 1 份数据
- 分叉点:只有在离接收者最近的路由器(最后一跳),数据才会被复制
形象的比喻:
- 单播是送外卖:你要给 100 个人送饭,你得跑 100 趟
- 组播是自来水管道:水厂(源)只出一根总管,到了小区(路由器)再分流,到了每户人家(交换机)再分流。无论多少户用水,水厂只管加压送水
4、灵魂拷问:收到包需要回 ACK 吗?
这是很多新手最容易纠结的问题。
答案是:数据层面通常不回,但控制层面必须回。
- 数据层面:沉默是金
组播通常基于 UDP。如果主机 B 收到数据后给主机 A 回一个 ACK,那么当有 10,000 个接收者时,主机 A 瞬间就会被 ACK 风暴淹没而死机。
所以,标准的组播应用(如 IPTV)是单向的。如果应用层需要可靠性(如文件分发),通常采用 NACK 机制:只有丢包了才回包请求重传,收到了就保持沉默。 - 控制层面:IGMP 协议
虽然数据不回包,但主机 B 必须通过 IGMP 协议 告诉路由器"我在听"。- 加入组:主机 B 发送 IGMP Report,告诉路由器"我要看这个频道"。
- 保活:路由器定期发送 IGMP Query,主机 B 回复 Report 说"我还在"。
- 离开:主机 B 发送 IGMP Leave,路由器就会把该端口从组播树剪枝。