# 网络监测 · NetworkManager 与移动性

> ICE 的移动性，眼睛是 NetworkManager——它枚举本机所有网卡、监测网络变化。这一章读 rtc_base 的 network.h:GetNetworks 列出接口、StartUpdating 与 SignalNetworksChanged 感知变化、网卡类型与网络成本，以及网络切换如何触发连接迁移让通话活下去。收尾第 2 部分。

- 作者：David（道雾轩）
- 专栏：音视频与 WebRTC 详解（https://daiw.org/manual/webrtc.md）
- 最后更新：2026-07-14
- 原文：https://daiw.org/manual/webrtc/network-monitoring
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

# 网络监测 · NetworkManager 与移动性

第 2 部分收尾，补上一块支撑 ICE 移动性的基石：**网络监测**。[采集候选](https://daiw.org/manual/webrtc/port-allocator)要知道「本机有哪些网卡」，[持续采集与 ICE 重启](https://daiw.org/manual/webrtc/nomination-and-restart)要知道「网络什么时候变了」——这些都由 `rtc_base` 里的 **`NetworkManager`**（`rtc_base/network.h`）提供。它是 ICE 感知网络世界的眼睛。

## NetworkManager：枚举与监测

`NetworkManager` 干两件事（`rtc_base/network.h`）：**枚举当前网卡**、**监测网络变化**。

```cpp
// rtc_base/network.h(节选)
virtual void StartUpdating() = 0;                       // 开始监测
virtual std::vector<const Network*> GetNetworks() const = 0;  // 列出当前网络接口
// SignalNetworksChanged —— 网络变化时发出信号
```

- **`GetNetworks()`** —— 返回本机当前所有可用的网络接口（`Network` 对象）：每块 Wi-Fi、有线、蜂窝网卡，连同它们的 IP 地址。[`PortAllocator`](https://daiw.org/manual/webrtc/port-allocator) 据此**为每个接口建 [Port](https://daiw.org/manual/webrtc/port-allocator)、采集候选**——这就是为什么一台多网卡设备会产出[众多候选](https://daiw.org/manual/webrtc/candidates)。
- **`StartUpdating()`** —— 启动监测。之后一旦网络拓扑变化（网卡上下线、IP 变更），`NetworkManager` 就发出 `SignalNetworksChanged`。文档说明：调用 `StartUpdating()` 后会**立即**先发一次信号（告知当前状态），此后每次变化再发。

## 网卡类型与网络成本

`NetworkManager` 不只是列地址，还知道每个网络的**类型**和**成本**。`network.h` 里有一个 `kDefaultNetworkIgnoreMask = ADAPTER_TYPE_LOOPBACK`——默认忽略环回接口（`127.0.0.1` 那种，对通话没用）。除环回外，还区分 Wi-Fi、蜂窝（cellular）、有线（ethernet）、VPN 等类型：

<Callout type="info">
  **网卡类型带来「网络成本」的概念——不是所有网都一样『便宜』。** 蜂窝数据要花流量钱、可能不稳；Wi-Fi / 有线通常免费且稳定。WebRTC 因此给不同网络赋予不同的**成本（cost）**，并让 [ICE 选路](https://daiw.org/manual/webrtc/ice-controller)**倾向低成本网络**——能走 Wi-Fi 就别走蜂窝。这个偏好会体现在[候选优先级](https://daiw.org/manual/webrtc/candidates)里。对移动设备，这个考量很实在：用户不希望一通视频电话把流量套餐吃光。所以「选哪条路」不只看快不快、通不通，还看**贵不贵**——工程要照顾真实世界的账单。
</Callout>

## 网络切换：连接迁移，通话不断

`NetworkManager` 最精彩的价值，是让通话**扛得住网络切换**。场景：你边走边视频，从家里 Wi-Fi 覆盖走到街上，Wi-Fi 断了、手机自动切到蜂窝。会发生什么？

```mermaid
flowchart TD
    W["通话中:走 Wi-Fi 网卡的连接"]
    W -->|"走出覆盖,Wi-Fi 网卡下线"| SIG["NetworkManager:SignalNetworksChanged"]
    SIG -->|"蜂窝网卡上线"| CG["持续采集:在蜂窝网卡上采新候选"]
    CG --> TRICKLE["trickle 给对端 → 配对新 Connection → 检查"]
    TRICKLE -->|"蜂窝路径通了"| SW["IceController 切到蜂窝连接"]
    SW --> C["通话继续(用户几乎无感,或短暂卡顿)"]
```

`NetworkManager` 感知到 Wi-Fi 网卡消失、蜂窝网卡出现，发出 `SignalNetworksChanged`；[持续采集](https://daiw.org/manual/webrtc/nomination-and-restart)据此在蜂窝网卡上[采集新候选](https://daiw.org/manual/webrtc/port-allocator)，[配成新 `Connection`、检查](https://daiw.org/manual/webrtc/connection-and-checks)、[选路切换](https://daiw.org/manual/webrtc/ice-controller)过去。整个过程**媒体尽量不中断**——这叫**连接迁移（connection migration）**。**没有 `NetworkManager` 的网络感知，就没有 WebRTC 的移动性**；有了它，通话才能跟着你从室内走到室外、从 Wi-Fi 换到 5G，一路不掉。

## 小结与第 2 部分回顾

**`NetworkManager`**（`rtc_base/network.h`）是 ICE 感知网络的眼睛：**`GetNetworks()`** 枚举本机网卡（供[采集候选](https://daiw.org/manual/webrtc/port-allocator)），**`StartUpdating()` + `SignalNetworksChanged`** 监测网络变化；它还懂**网卡类型与成本**（Wi-Fi/蜂窝/有线，让[选路](https://daiw.org/manual/webrtc/ice-controller)倾向低成本网络）。网络切换时，它的信号触发[持续采集与选路切换](https://daiw.org/manual/webrtc/nomination-and-restart)，实现**连接迁移**——通话跟着网络环境走而不断。

**第 2 部分「ICE 与连接建立」到此完整**：从 [ICE 总览](https://daiw.org/manual/webrtc/ice-overview) → [四种候选](https://daiw.org/manual/webrtc/candidates) → [采集与 Port](https://daiw.org/manual/webrtc/port-allocator) → [STUN](https://daiw.org/manual/webrtc/stun-protocol) → [TURN](https://daiw.org/manual/webrtc/turn) → [Connection 与检查](https://daiw.org/manual/webrtc/connection-and-checks) → [总指挥 P2PTransportChannel](https://daiw.org/manual/webrtc/p2p-transport-channel) → [选路 IceController](https://daiw.org/manual/webrtc/ice-controller) → [提名与重启](https://daiw.org/manual/webrtc/nomination-and-restart) → 网络监测，我们看清了 WebRTC 怎么在充满 NAT 的真实互联网上，**为两个端点打通并维持一条路**。

路通了，但还是**明文**——下一步必须加密。第 3 部分进入**安全**：DTLS 怎么在这条路上握手拿密钥，SRTP 怎么加密每一个媒体包。👉 第 3 部分即将展开。

## 参考资料

- [1] libwebrtc 源码.`rtc_base/network.h` / `.cc`（`NetworkManager`、`GetNetworks`、`StartUpdating`、`SignalNetworksChanged`、网卡类型）。
- [2] libwebrtc 源码.`p2p/base/port_allocator.cc`（用 `NetworkManager` 采集）、`g3doc/ice.md`。
- [3] IETF RFC 8445「ICE」§ Gathering Candidates；连接迁移相关实践。
