一个数据包能发给几台机器?聊聊单播、广播、组播和任播
前言
如果你折腾过网络,大概率把 DNS 改成过 1.1.1.1 或者 8.8.8.8。
不知道你有没有想过一个问题:这两个地址全世界的人都在用。你在北京 ping 1.1.1.1,延迟 30ms;别人在法兰克福 ping 同一个地址,延迟可能只有 5ms。
按常理,一个 IP 地址对应一台服务器。如果 1.1.1.1 真的是一台机器,那它要么在中国,要么在德国,总有一边的人延迟会很难看。而且全球这么多查询打到一台机器上,早就把它打垮了。
问题就出在这里:1.1.1.1 根本不是一台机器,而是分布在全球各地的一大堆机器,它们共用了同一个 IP 地址。
这种玩法叫任播(Anycast),是四种数据包投递方式里最年轻的一个。要讲清楚它为什么可行,得先把前面三个老家伙讲清楚:单播、广播、组播。
四个词,一件事
这四个词说的是同一件事:一个数据包发出去,能到几台机器、到哪几台。
用寄信来打比方:
- 单播(Unicast):信封上写了门牌号,只送到那一家。
- 广播(Broadcast):小区大喇叭喊话,不管你想不想听,所有人都听见了。
- 组播(Multicast):订报纸——订了才送,没订的不收。
- 任播(Anycast):连锁店客服电话,全国一个号码,接电话的是离你最近的那家店。
下面一个一个说。
单播:互联网的默认
单播就是一个地址对应一个接口,点对点送达。你访问网站、SSH 到服务器、给 NAS 传文件,全是单播。
单播有个前提:你得先知道对方的地址。在互联网上是 IP,在局域网里真正干活的是 MAC 地址。所以通信开始之前还有一步”把 IP 翻译成 MAC”——这步靠的是后面要讲的广播。单播和广播不是替代关系,是搭档。
单播的瓶颈也很明显:一对一。一千个人看同一场直播,服务器就得发一千份。
广播:局域网里的喊话
广播最简单粗暴:数据包发给广播地址,同一个广播域里所有设备都收到。
IPv4 有两种广播地址:
- 受限广播:
255.255.255.255,只在本网段有效。 - 定向广播:某个网段的最后一个地址,比如
192.168.1.0/24的192.168.1.255。
二层上,广播帧的目的 MAC 是 ff:ff:ff:ff:ff:ff,交换机会从所有端口转出去。
ARP:广播最经典的应用
你的电脑要给网关 192.168.1.1 发数据,但不知道网关的 MAC 地址。于是广播喊一句:”谁是 192.168.1.1?告诉我你的 MAC。”网关听到后回复,你的电脑记进 ARP 缓存:
1 | 你的电脑 网关 (192.168.1.1) |
Linux 上可以看这个缓存:
1 | ip neigh |
1 | 192.168.1.1 dev eth0 lladdr aa:bb:cc:dd:ee:ff REACHABLE |
(示例输出,MAC 地址以实际环境为准。)
注意:ARP 是广播,广播出不了局域网——路由器不转发广播包。所以 ARP 只能问同网段的设备,跨网段必须走路由。
广播另一个常见场景是 DHCP 发现。设备刚接入网络,没有 IP 地址,怎么找 DHCP 服务器?只能广播。往 255.255.255.255 发一个 DHCP Discover,DHCP 服务器收到后回复 Offer。在拿到自己的 IP 之前,广播是设备唯一的通信手段——它连自己是谁都不知道。
为什么广播被严格控制
广播的代价是每台设备都必须停下来看一眼,哪怕这个包跟自己没关系。设备多了,这种开销很可观。
更严重的是广播风暴。网络里有环路的话,广播包会被无限复制转发,几秒钟打瘫整网。还有早年的 smurf 攻击,利用定向广播把一个包放大成几百份打向受害者。所以现在路由器默认不转发定向广播。
广播好用,但太吵。
组播:只发给订阅者
既然广播太吵,能不能只发给想听的人?这就是组播。
IPv4 留了一段地址给组播:224.0.0.0/4(224.0.0.0 到 239.255.255.255)。想收某个组播流的设备,通过 IGMP 协议告诉路由器”我要加入这个组”,路由器只往有订阅者的方向转发。二层上,组播 IP 映射到 01-00-5e 开头的 MAC,交换机配合 IGMP Snooping 也能做到只往需要的端口转发。
组播最典型的应用是运营商 IPTV。一千户人家看同一个频道,源头只发一份,网络设备在岔路口自动复制。省的是骨干带宽。企业里也常用:视频会议的音视频分发、OSPF 的邻居发现(224.0.0.5、224.0.0.6)、mDNS 局域网设备发现(224.0.0.251,macOS 的 Bonjour 和 Linux 的 Avahi 都用它)。
几个常见的知名组播地址:
224.0.0.1:本网段所有主机224.0.0.2:本网段所有路由器224.0.0.5/224.0.0.6:OSPF 专用224.0.0.251:mDNS
好奇的话可以在 Linux 上抓一下组播包:
1 | sudo tcpdump -ni eth0 multicast |
(eth0 换成实际网卡名。能看到 224.x 或 ff02:: 开头的包就是组播流量。)
组播和广播的区别:广播是”我喊了你们都得听”,组播是”你订阅了我才发”。而且广播天生出不了局域网,组播理论上可以跨网段路由——只不过公网上运营商基本不给你转组播,所以组播主要活在运营商内网、企业内网这类受控环境里。
IPv6 干脆取消了广播
IPv6 的设计者显然也觉得广播太糙。RFC 4291 原话:
There are no broadcast addresses in IPv6, their function being superseded by multicast addresses.
IPv6 里没有广播地址。 原来广播干的活全用组播替代。要通知链路上所有设备,发给 ff02::1 就行。
ARP 也取消了。IPv6 用 NDP(邻居发现协议)代替,查询时发给 Solicited-Node 组播地址——这个地址根据目标 IP 的后 24 位算出来,只有可能是目标的机器才会加入。原来喊一嗓子全村听,现在只敲可能相关的几家门。
任播:同一个地址,发给最近的那个
任播的定义:同一个 IP 地址配在很多台机器上,路由协议负责把包送到”最近”的那一台。
这里的”最近”是路由意义上的(BGP 路径最短),不一定是地理最近,但两者通常正相关。
任播不是一种新地址
IPv4 里没有专门的任播地址段。任播用的就是普通单播地址,只不过从全球多个机房同时用 BGP 宣告出去:
1 | 单播:一个地址,一个地方宣告 → 路由到唯一的那台 |
Cloudflare 在北京和法兰克福各有一台服务器,都宣告 1.1.1.1/32。从上海 traceroute 最后一跳到北京,从巴黎 traceroute 最后一跳到法兰克福。你可以在自己机器上试:
1 | traceroute 1.1.1.1 |
前几跳是自家路由器和运营商,后面就是到最近 Cloudflare 节点的路径。
任播这个概念 1993 年就有人提了(RFC 1546),但真正跑起来靠的是 BGP。多个机房同时宣告同一个前缀,路由器按 AS 跳数选最短的那条路,包自然飞向最近的机房。RFC 4786(2006 年)专门记录了这种 BGP-based anycast 的运维经验。
IPv6 在 RFC 4291 里把任播定为正式地址类型,但也说得很清楚:任播地址取自单播空间,语法上和单播无法区分,节点得被显式配置才知道自己是任播地址。
同一个 IP 为什么不会冲突?
这是关于任播最容易让人困惑的地方。同一个网段两台服务器配同一个 IP,ARP 会抢答,交换机 MAC 表会翻转,网络直接乱套。
任播不冲突的原因很简单:这些服务器根本不在同一个网段。
1 | 互联网骨干网(BGP 路由器们) |
每个节点在独立的自治系统里,有独立的网段和路由表。1.1.1.1 在北京机房只配在一台机器上,法兰克福也一样——每个局部网络里 IP 仍然唯一,ARP 永远碰不到一起。
每个机房用 BGP 向上游宣告”1.1.1.1/32 从我这里走”,这条路由传播到全球路由器。骨干网上每台路由器看到 1.1.1.1/32 有好几条可达路径指向不同 AS,按 BGP 选路规则(最短 AS 路径、本地优先级等)挑一条最优的。
实际部署里还有个细节。前面画的是三个不同 AS,最干净。但一个大厂可能同一个 AS 内好几个机房都跑任播。如果所有路由器都宣告同一条 /32,外部网络可能从一个不那么近的入口钻进来导致绕路。
怎么控制?靠 BGP 社区属性。常见做法是给任播路由打上 no-export 标记,告诉邻居”这条路由只在我本地用,别往外传”:
- AS 内部:所有路由器认得这条任播路由,流量在内部选最近的节点。
- AS 外部:这条路由不传播出去,外部只看到聚合后的前缀(比如
/24),不被/32主机路由搅乱。
RFC 4786 专门讨论了这个场景。宣告太窄外部找不到你,宣告太宽路由表压力大还会绕路,找到平衡点是任播运维的核心工作。
BGP 天然支持同一个前缀多条路径——这是它设计的核心能力。每台路由器独立选路,不需要中心化协调。
RFC 4291 还提了一个边界情况:如果任播节点散布在全球没有任何拓扑聚集性的地方,这条路由就得作为独立主机路由在每台路由器上维护,对路由表规模是压力。所以全球分布的任播集合数量有限制。实际操作中,大厂会把节点组织成有拓扑层次的集群,尽量让前缀可聚合。
任播用在哪
DNS 根服务器。逻辑上全球 13 个根服务器身份(a.root-servers.net 到 m),物理上通过任播在全球部署了上千个节点。你查根服务器,查到的是离你最近的那个。
公共 DNS 也是:1.1.1.1、8.8.8.8、9.9.9.9 全是任播。CDN 更不用说,Cloudflare 整个网络跑在任播上。
好处:
- 天然就近访问,延迟低。
- 同一个地址的流量自动摊到全球各机房。
- 抗 DDoS:攻击流量按路由走,被分散到各机房消化。
- 某个机房下线,撤销 BGP 宣告,流量自动流向下一个最近的节点。
TCP over 任播靠不靠谱
任播对 DNS 这种一来一回的场景几乎完美。对 TCP 长连接,理论上的坑是:BGP 路由抖动,”最近节点”变了,后续的包飞到一个没有连接状态的机房,连接直接断。
早期说法是”任播只适合 UDP,不适合 TCP”。这个说法今天基本过时了。骨干网路由足够稳定,大厂也会刻意调路由避免流量在节点间来回跳。Cloudflare 的 HTTPS 全站跑在任播上,就是最好的证据。
但自己玩 BGP 宣告搞任播时,这个坑是真实存在的。
验证一下
1 | curl https://1.1.1.1/cdn-cgi/trace |
输出里有 colo= 后面跟机房三字码,比如 PVG(上海)、FRA(法兰克福)、NRT(东京)。换个 VPN 节点再跑,机房代码会变——同一个地址,不同的机器在回答你。
几个容易搞混的点
组播和任播很容易混。区别在于方向:组播是一个包发给多个接收者,任播是多个候选节点里只选一个。
任播和 CDN 的智能 DNS 调度也不是一回事。DNS 调度在解析阶段就选好了机房,用户拿到的 IP 每次可能不同;任播是所有人拿到同一个 IP,路由在转发阶段才决定去哪。DNS 调度有 TTL 缓存的延迟,任播没有。
任播不是负载均衡。 它只看路由距离,不看节点忙不忙。两个节点离你一样近但负载差十倍,任播还是会把流量往近的塞。需要精细调度的话,得在任播上面再叠一层负载均衡。
四种方式放在一起看
| 方式 | 发给谁 | 典型场景 | 主要限制 |
|---|---|---|---|
| 单播 | 确定的一台 | 上网、SSH、文件传输 | 一对多时要逐个复制 |
| 广播 | 广播域内所有设备 | ARP、DHCP 发现 | 出不了局域网,IPv6 已取消 |
| 组播 | 订阅了该组的一组设备 | IPTV、OSPF、mDNS | 公网基本不路由组播 |
| 任播 | 共享地址中最近的一台 | 根 DNS、公共 DNS、CDN | 路由抖动可能影响长连接 |
总结
单播、广播、组播、任播,演进方向很明确:投递越来越精确,打扰越来越少。
广播被 IPv6 淘汰不是因为它没用,而是组播能用更小的代价干同样的活。任播看起来最”新”,但 1993 年就有人提了,真正普及是 BGP 和 CDN 把它带起来的。这四种方式不是替代关系——你的电脑上网时,单播在传数据,ARP 广播在解析地址,NDP 组播在发现邻居,任播在帮你连 DNS。四个家伙一起干活。
下次 ping 1.1.1.1,看到那个稳定得不像话的低延迟,你就知道:回包的那台机器大概率就在你附近。而地球另一端,有另一台机器正顶着同一个地址,为别人干着同样的事。
参考资料
- 标题: 一个数据包能发给几台机器?聊聊单播、广播、组播和任播
- 作者: Kaku
- 创建于 : 2026-07-29 17:30:00
- 更新于 : 2026-07-29 17:19:40
- 链接: https://www.kakunet.top/2026/07/29/一个数据包能发给几台机器?聊聊单播、广播、组播和任播/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。