一个数据包能发给几台机器?聊聊单播、广播、组播和任播

Kaku Lv4

前言

如果你折腾过网络,大概率把 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/24192.168.1.255

二层上,广播帧的目的 MAC 是 ff:ff:ff:ff:ff:ff,交换机会从所有端口转出去。

ARP:广播最经典的应用

你的电脑要给网关 192.168.1.1 发数据,但不知道网关的 MAC 地址。于是广播喊一句:”谁是 192.168.1.1?告诉我你的 MAC。”网关听到后回复,你的电脑记进 ARP 缓存:

1
2
3
4
5
6
你的电脑                      网关 (192.168.1.1)
| ---- ARP Request (广播) ---> | "谁是 192.168.1.1?"
| |
| <--- ARP Reply (单播) ---- | "我是 aa:bb:cc:dd:ee:ff"
|
| [记入 ARP 缓存,后续直接用 MAC 通信]

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.5224.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.xff02:: 开头的包就是组播流量。)

组播和广播的区别:广播是”我喊了你们都得听”,组播是”你订阅了我才发”。而且广播天生出不了局域网,组播理论上可以跨网段路由——只不过公网上运营商基本不给你转组播,所以组播主要活在运营商内网、企业内网这类受控环境里。

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
2
单播:一个地址,一个地方宣告   → 路由到唯一的那台
任播:一个地址,N 个地方宣告 → 路由到"最近"的那台

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
2
3
4
5
6
           互联网骨干网(BGP 路由器们)
/ | \
/ | \
AS 13335 (北京) AS 13335 (法兰克福) AS 13335 (圣保罗)
1.1.1.1/32 1.1.1.1/32 1.1.1.1/32
[Cloudflare] [Cloudflare] [Cloudflare]

每个节点在独立的自治系统里,有独立的网段和路由表。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.18.8.8.89.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 进行许可。
评论