SCTP 要 TCP 的可靠性,但不要 TCP 的队头阻塞:一个连接里多条独立流。 它还支持「一个端点多个 IP」,一条路径断了自动换另一条。
6.4.7 讲了 TCP 的队头阻塞,SCTP 的第二行就是针对它的。 5.8.5 的 Mobile IP 想解决「换网不断线」,SCTP 用多宿主在传输层做了一遍。
一、它想解决什么
SCTP 最早叫「流控制传输协议」,是电话网那边提出来的: 他们要在 IP 上传信令,需要「可靠」但不需要「严格按序阻塞」。 TCP 的问题是「一条流」:一个包丢了,后面所有数据都得等,哪怕它们属于「不同的业务」。 SCTP 的做法是「一个连接里开多条流」,每条流各自有序,流与流之间互不影响。
二、四个能力对比
| 能力 | TCP | SCTP |
|---|---|---|
| 可靠性 | 有 | 有 |
| 多流 | 没有 | 一个连接多条独立流 |
| 多宿主 | 没有 | 一端可配多个 IP |
| 消息边界 | 字节流,无边界 | 按消息投递 |
第二行解决「队头阻塞」:一个连接里同时传「信令」和「文件」时,文件慢不该拖住信令。 这在电话网里是刚需,因为信令晚一点就可能掉话。 第三行是「换网不断线」的网络层方案: 两端各配多个 IP,一条路径坏了自动切另一条,不需要等重连。 这比 5.8.5 的 Mobile IP 更直接——它不靠「家乡代理转发」,而是靠「自己有好几个地址」。 第四行省一层拆包逻辑:TCP 是字节流,应用要自己划边界; SCTP 保留消息边界,发一条就是一条。 这一点和 UDP 一样,但它又是可靠的——等于「UDP 的边界加 TCP 的可靠」。
三、为什么没普及
第一个原因是「中间设备不认」:SCTP 用的是独立的协议号 132, 很多 NAT 和防火墙不认识它,直接丢。 而 NAT 尤其麻烦:它要改端口,可 SCTP 的「端口」语义和 TCP 不一样。 第二个原因是「应用层解决了」:「多流」这件事,HTTP/2 的多路复用做到了; 「多路径」这件事,MPTCP 和 QUIC 的连接迁移也做到了。 既然应用层能解决,就没必要换传输层协议。 所以它主要活在两个地方:电信信令(7 号信令 over IP)和 WebRTC 的数据通道。 这两个场景的共同点是「自己控制两端」,不需要求中间设备配合。
四、动手 Demo:SCTP 想同时要「可靠」和「不阻塞」
把 TCP 和 SCTP 的四项能力摆在一起看。 重点是「多流」和「多宿主」这两行。
rows = (('可靠性', '有', '有'),
('多流', '没有', '一个连接多条流'),
('多宿主', '没有', '一端多 IP'),
('消息边界', '字节流', '按消息投递'))
for a, b, c in rows:
print('%-8s %-8s %s' % (a, b, c))
实跑输出:
--------------------------------------------------------------------
SCTP 想同时要「可靠」和「不阻塞」
--------------------------------------------------------------------
**SCTP 是电话网那边提出来的**:**它要 TCP 的可靠性,但不要 TCP 的「队头阻塞」。**
能力 TCP SCTP
-------------------------------------------------------------------
**可靠性** **有** **有**
**多流** **没有** **一个连接里多条独立流**
**多宿主** **没有** **一个端点多个 IP**
**消息边界** **字节流,没有边界** **按消息投递**
**第二行解决的是「队头阻塞」**:**TCP 里一个包丢了,后面所有数据都得等**(D188 演示过);
**SCTP 的多条流各自独立**,**一条流卡住不影响别的流。**
**这在一个连接里同时传「信令」和「文件」时特别有用**——**文件慢不该拖住信令。**
**第三行是「换网不断线」的网络层方案**:**两端各配多个 IP,一条路径坏了自动切另一条**,
**不需要等重连。**
**第四行是「按消息收」**:**TCP 是字节流,应用要自己划边界**,**SCTP 直接保留消息边界**,
省掉一层拆包逻辑。
**它为什么没普及**:**中间设备不认**(很多 NAT 和防火墙不认识 SCTP),
**而「多流」这件事在应用层也能做**(比如 HTTP/2 的多路复用)。
**所以它主要活在「电信信令」领域**(7 号信令 over IP),**以及 WebRTC 的数据通道里。**
「多宿主」是最容易被低估的一项:它意味着「同一条连接可以有好几条路径」, 主路径断了自动切备路径,应用的连接不中断。 这在「手机在 WiFi 和蜂窝之间切换」时特别有价值——可惜实际部署太少,因为「两端都得支持」。 「消息边界」这一项和 UDP 一样:所以「一次发一条、一次收一条」在 SCTP 上成立, 而在 TCP 上不成立。 这一点在写协议实现时差别很大——用 TCP 就得自己写「长度前缀」或者「分隔符」。 最后一个判断:SCTP 的设计几乎没有毛病,问题全在「部署」。 而「部署」这件事,取决于「有没有人愿意先动」—— 操作系统支持了,中间设备不认;中间设备改了,应用又不用。 这就是「协议好不等于协议活」的现实。
30 秒实验
- 想一下:多流和 TCP 的多路复用有什么不同?
- 想一下:多宿主和 Mobile IP 的目标一样吗?
- 想一下:为什么 SCTP 在 NAT 环境下特别难?
常见误区
- 以为「SCTP 是 TCP 的替代品」。 是另一个取舍,而且部署极少。
- 以为「多流就是多个连接」。 是一个连接里的多条逻辑流,共享同一套拥塞控制。
- 以为「消息边界是小事」。 它省掉一层拆包逻辑,在协议实现里差别很大。
自测三问(点开对答案)
1. SCTP 的多流解决什么问题? —— **TCP 的队头阻塞**:一条流卡住不影响其他流。 2. 多宿主是什么? —— **一个端点配多个 IP**,一条路径断了自动切另一条,连接不断。 3. SCTP 为什么没普及? —— **中间设备不认(协议号 132),而「多流、多路径」在应用层也能做。**下一节看一个「不可靠但讲礼貌」的协议:DCCP。
- ☐ (本节完,下一节 6.5.3 DCCP)