# SCTP 可靠传输 · TSN、SACK 与重传

> SCTP 默认提供可靠、有序的传输——每块数据编 TSN，接收方用 SACK 选择性确认，缺的块重传。这一章讲清 TSN 序号、SACK 比 TCP 累积确认精细在哪、以及 dcSCTP 的重传队列如何补回丢失的数据块。

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

# SCTP 可靠传输 · TSN、SACK 与重传

SCTP **默认**像 TCP 一样提供**可靠、有序**的传输（丢了必重传、乱了会重排）。它靠三样东西做到：**TSN**（给数据编号）、**SACK**（确认收到）、**重传**（补回丢的）。这一章看这套机制，它是 SCTP 的地基（[部分可靠](https://daiw.org/manual/webrtc/sctp-partial-reliability)是在它之上“减配”）。

## TSN：给每块数据编号

每个 [DATA chunk](https://daiw.org/manual/webrtc/sctp-chunks-packets) 带一个 **TSN（Transmission Sequence Number）**——全 association 唯一、递增的序号。它的作用和 [RTP 序号](https://daiw.org/manual/webrtc/rtp-packet)、TCP 序号一样：**让接收方能发现丢失（TSN 跳号）、重排乱序（TSN 排序）**。TSN 是 SCTP 可靠性的坐标系——一切“收到没、按顺序没”的判断，都基于它。

## SACK：选择性确认

接收方靠 **SACK(Selective ACKnowledgement)chunk** 告诉发送方收到了什么：

<Callout type="info">
  **SACK 报告两部分：① 一个**累积 TSN**（到这个号为止都连续收到了）② 若干**gap ack 块**（累积号之后，又不连续地收到了哪些）。这个“选择性”比 TCP 的纯累积确认**精细得多**。** 举例：收到了 TSN 1,2,3,5,6（缺 4）。SACK 报告：“累积到 3（1-3 连续收齐），另外 gap 块 5-6 也收到了（但 4 缺）。” 发送方一看就明白：**只有 4 丢了，重传 4 就行**，5、6 别重发。

  对比 [TCP 的累积确认](https://daiw.org/manual/webrtc/sctp-reliability)：TCP 只能说“我连续收到 3 了”，不能告诉你 5、6 其实也到了——于是 TCP 重传时可能把 4、5、6 都重发（或靠 SACK 扩展补救）。SCTP 把选择性确认**做进协议核心**，重传更精准、更省带宽。这在[丢包环境](https://daiw.org/manual/webrtc/nack-rtx)下优势明显——只补真正丢的，不做无用功。dcSCTP 的 `net/dcsctp/rx/`（接收侧）负责生成 SACK、`net/dcsctp/tx/`（发送侧）负责据 SACK 管理[重传](https://daiw.org/manual/webrtc/sctp-reliability)。
</Callout>

## 重传：补回丢的块

发送方据 [SACK](https://daiw.org/manual/webrtc/sctp-reliability) 得知哪些 [TSN](https://daiw.org/manual/webrtc/sctp-reliability) 丢了，就**重传**它们。触发重传有两种（和 TCP 类似）：

- **快速重传** —— 如果一个 [TSN](https://daiw.org/manual/webrtc/sctp-reliability) 被多个 SACK 报告为“缺”（gap 一直在它前面），说明它多半真丢了（而非只是晚到），**立即重传**，不等超时。
- **超时重传** —— 发出的块在一个 RTO（重传超时）内没被确认，**超时重传**。RTO 根据 [RTT](https://daiw.org/manual/webrtc/connection-and-checks) 动态估算（测往返、算超时）。

<Callout type="info">
  **发送方维护一个“重传队列”——发出但还没被 [SACK](https://daiw.org/manual/webrtc/sctp-reliability) 确认的块都留在里面（类似 [RtpPacketHistory](https://daiw.org/manual/webrtc/rtp-sender) 留底），确认了才移除，该重传了就从这里取。** dcSCTP 的 `net/dcsctp/tx/`（如 `retransmission_queue`）就是这个队列。它和[视频的重传](https://daiw.org/manual/webrtc/nack-rtx)、[TCP 的重传](https://daiw.org/manual/webrtc/sctp-reliability)是同一个思想：**留一份底，丢了能补**。区别在触发方式——SCTP 靠[发送方看 SACK 主动补](https://daiw.org/manual/webrtc/sctp-reliability)（sender-driven），而 [WebRTC 媒体的 NACK](https://daiw.org/manual/webrtc/nack-rtx) 靠接收方主动要（receiver-driven）。两种都对，取决于协议设计。SCTP 的这套 TSN + SACK + 重传，让它默认就是**可靠**的——除非你[显式放宽](https://daiw.org/manual/webrtc/sctp-partial-reliability)。
</Callout>

## 有序交付

除了可靠（不丢），SCTP 默认还**有序**（不乱）。它给每条[流](https://daiw.org/manual/webrtc/sctp-streams)的消息编一个**流序号（SSN / MID）**，接收方**按序**交付给应用——即使 [TSN](https://daiw.org/manual/webrtc/sctp-reliability) 层面乱序到达，也会**重排**后再上交。注意：有序是**按流**的——[不同流之间互不影响](https://daiw.org/manual/webrtc/sctp-streams)（A 流的乱序不阻塞 B 流，这是[SCTP 无队头阻塞](https://daiw.org/manual/webrtc/data-channel-overview)的关键）。而“有序”这个特性，[数据通道可以关掉](https://daiw.org/manual/webrtc/sctp-partial-reliability)（要无序低延迟时）——下一章讲这种“减配”。

## 小结与下一章

SCTP **默认可靠有序**，靠三样：**TSN**（给每 [DATA 块](https://daiw.org/manual/webrtc/sctp-chunks-packets)唯一递增编号，发现丢失 / 重排）、**SACK**（选择性确认：累积号 + gap 块，比 [TCP 累积确认精细](https://daiw.org/manual/webrtc/sctp-reliability)，只补真丢的）、**重传**（[快速重传 + 超时重传](https://daiw.org/manual/webrtc/sctp-reliability)，发送方维护重传队列留底，`dcsctp/tx`）。**有序**按[流](https://daiw.org/manual/webrtc/sctp-streams)保证（流间不阻塞）。这套是 SCTP 的地基。

但数据通道有时**不想要**完全可靠 / 有序（实时数据宁可丢旧的）。SCTP 怎么“减配”成部分可靠？下一章讲这个杀手锏。👉 [SCTP 部分可靠](https://daiw.org/manual/webrtc/sctp-partial-reliability)。

## 参考资料

- [1] libwebrtc 源码.`net/dcsctp/tx/`（重传队列、SACK 处理）、`net/dcsctp/rx/`（生成 SACK、重排）。
- [2] IETF RFC 9260「SCTP」§ 6（可靠传输、SACK、重传）。
- [3] 关联[RtpPacketHistory 留底](https://daiw.org/manual/webrtc/rtp-sender)、[NACK 重传](https://daiw.org/manual/webrtc/nack-rtx)。
