# 数据通道与 SCTP 总览 · 传任意数据的那条路

> 数据通道传任意数据，底层走 SCTP over DTLS。这一章读 g3doc/sctp_transport.md:SctpTransport 如何封装一个 SCTP association、它和 DTLS 传输的关系、以及为什么 WebRTC 选 SCTP 而非直接用 TCP 或 UDP。为深入 dcSCTP 铺垫。

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

# 数据通道与 SCTP 总览 · 传任意数据的那条路

音视频讲完，进入 WebRTC 的第三种媒体——**数据通道**：传任意数据（文件、游戏状态、聊天）。[第 1 部分的 `DataChannelController`](https://daiw.org/manual/webrtc/data-channel-controller) 讲了它的控制面，第 8 部分深入它的**底层协议 SCTP**（`net/dcsctp/`，[242 个文件](https://daiw.org/manual/webrtc)）。先总览。

## 为什么是 SCTP

[数据通道那章](https://daiw.org/manual/webrtc/data-channel-controller)说过，数据通道走 **SCTP over [DTLS](https://daiw.org/manual/webrtc/dtls-handshake)**。为什么不直接用 TCP 或 UDP？

<Callout type="info">
  **SCTP（Stream Control Transmission Protocol）提供了 TCP 和 UDP 都给不了的东西：**可调的可靠性**和**多流**。**

  - **TCP 太死板** —— TCP **强制**完全可靠 + 完全有序。但数据通道有时不想要这个（实时游戏状态宁可丢旧的、也不要等重传）。而且 TCP 的[队头阻塞](https://daiw.org/manual/webrtc/data-channel-controller)：一个包丢了，后面的全卡住等它——多路数据挤一条 TCP 时，一路的丢包拖累所有路。
  - **UDP 太原始** —— UDP 什么保证都没有，要可靠 / 有序得自己造轮子。
  - **SCTP 恰到好处** —— 它像“可配置的 TCP”：[每条流的可靠性 / 有序性可独立设](https://daiw.org/manual/webrtc/sctp-partial-reliability)（完全可靠、部分可靠、完全不可靠都行），且**多流**——[一个 association 里多条独立的流](https://daiw.org/manual/webrtc/sctp-streams)，一路丢包不阻塞其他路。这正好匹配[数据通道“可靠性可调 + 多通道复用”](https://daiw.org/manual/webrtc/data-channel-controller)的需求。

  所以 WebRTC 选 SCTP——**但不直接把 SCTP 跑在 IP 上**（那要操作系统支持、还过不了 NAT），而是把它**跑在 [DTLS](https://daiw.org/manual/webrtc/dtls-handshake) 之上**（SCTP over DTLS over [ICE](https://daiw.org/manual/webrtc/ice-overview)），既借了 [DTLS 的加密](https://daiw.org/manual/webrtc/security-overview)、又借了 [ICE 的 NAT 穿越](https://daiw.org/manual/webrtc/ice-overview)。一举多得。
</Callout>

## SctpTransport：封装 association

WebRTC 里代表这条 SCTP 连接的，是 **`SctpTransport`**（`pc/sctp_transport.h`）。g3doc/sctp_transport.md 说明：

> The `webrtc::SctpTransport` class **encapsulates an SCTP association**.

一个 SCTP **association**（关联）= 两端之间的一条 SCTP 连接（[类似 TCP 的一个 connection](https://daiw.org/manual/webrtc/sctp-association)）。所有数据通道**复用这一个 association**（[靠 stream id 区分](https://daiw.org/manual/webrtc/sctp-streams)）。层次（g3doc）：

- **`SctpTransport`**(`pc/`)—— 面向用户的封装，[引用计数、归 PeerConnection 拥有](https://daiw.org/manual/webrtc/peer-connection-object)，暴露状态观察（状态变化回调在 [network 线程](https://daiw.org/manual/webrtc/threading-model)）。
- **`SctpTransportInternal`**(`media/sctp/`)—— 内部实现，**拥有两个对象：SCTP association + [DTLS 传输](https://daiw.org/manual/webrtc/dtls-handshake)**。DTLS 传输是它收发字节的通道——SCTP 的包，经 DTLS [加密](https://daiw.org/manual/webrtc/srtp-encryption)后发出。

```mermaid
flowchart TD
    APP["数据通道 API(send/onmessage)"] --> SDC["SctpDataChannel(第 1 部分)"]
    SDC --> ST["SctpTransport / SctpTransportInternal"]
    ST --> ASSOC["SCTP association(dcSCTP)"]
    ASSOC -->|"SCTP 包"| DTLS["DTLS 传输(加密,第 3 部分)"]
    DTLS -->|"经 ICE 通路"| NET["网络"]
```

## dcSCTP：从零重写的 SCTP

这里有个重要的工程决定：WebRTC 的 SCTP 实现，是 Google **从零写的**——**dcSCTP**（`net/dcsctp/`），而非沿用老的第三方库（usrsctp）。为什么大费周章重写一个协议栈？[下一章](https://daiw.org/manual/webrtc/dcsctp-intro)细说，先剧透原因：老库难维护、难测试、有安全隐患，而 dcSCTP 用现代 C++、**sans-IO 设计**（[不碰网络、纯逻辑](https://daiw.org/manual/webrtc/dcsctp-intro)、易测试）重写，更安全、更可控。这是 WebRTC “[密码学 / 协议宁可自己写一个高质量的](https://daiw.org/manual/webrtc/boringssl-integration)”哲学的又一次体现（呼应 [AEC3 自带回声消除](https://daiw.org/manual/webrtc/aec3-echo-problem)）。

## 小结与下一章

**数据通道**传任意数据，走 **SCTP over [DTLS](https://daiw.org/manual/webrtc/dtls-handshake) over [ICE](https://daiw.org/manual/webrtc/ice-overview)**。选 SCTP 因为它兼具 TCP 没有的**[可调可靠性](https://daiw.org/manual/webrtc/sctp-partial-reliability)**和**[多流（无队头阻塞）](https://daiw.org/manual/webrtc/sctp-streams)**，恰配[数据通道需求](https://daiw.org/manual/webrtc/data-channel-controller)。**`SctpTransport`**（[pc/，封装 association](https://daiw.org/manual/webrtc/peer-connection-object)）/ **`SctpTransportInternal`**（拥有 association + [DTLS 传输](https://daiw.org/manual/webrtc/dtls-handshake)）是 WebRTC 侧的代表。SCTP 实现是 Google 从零重写的 **dcSCTP**（`net/dcsctp/`）。

下一章看 dcSCTP 本身——为什么重写、以及它精妙的 **sans-IO** 设计。👉 [dcSCTP 从零实现](https://daiw.org/manual/webrtc/dcsctp-intro)。

## 参考资料

- [1] libwebrtc 源码.`g3doc/sctp_transport.md`、`pc/sctp_transport.h`、`media/sctp/sctp_transport_internal.h`。
- [2] libwebrtc 源码.`net/dcsctp/`（dcSCTP 实现）。
- [3] IETF RFC 9260「SCTP」、RFC 8831「WebRTC Data Channels」。
