Reading

现代通信协议:从可靠传输到实时媒体与消息语义


假设我们正在做一个在线白板:打开页面后,两个人可以一起画图、移动光标、语音交流,还能上传文件。画完的内容需要保存到服务器。

这些数据都经过网络,但它们对网络的要求并不相同。

上传文件时,少一个字节都不行,慢一点通常可以接受。移动光标时,新的位置已经到了,半秒前的位置反而没有必要补回来。语音也有时效性,但丢掉一段声音后,还需要决定怎样维持连续播放。保存白板时,即使所有请求字节都成功发送,也不代表服务器已经把修改写进数据库。

因此,“选一个更快的协议”还不是一个足够明确的问题。我们要先问:哪些数据必须完整?哪些数据过时就可以丢弃?收到什么,才算事情完成?

本文沿着这三个问题展开:先从 TCP 的可靠传输走到 QUIC 和 HTTP/3,再解释实时通信为什么需要 WebRTC、WebTransport 这样的接口,最后讨论 gRPC、MQTT、DDS 和 CoAP 如何表达应用真正关心的操作与消息。阅读时只需要知道:网络把数据拆成包发送,包可能丢失、重复、乱序,往返一次需要一定时间。

先分清:这些名字并不处于同一层

一次“保存白板”的远程调用,可以通过 gRPC 表达,通过 HTTP/2 承载,再由 TCP 传输。它们不是三个相互替代的方案,而是在回答不同的问题。

要解决的问题代表机制或协议尚未替应用解决的事
如何在网络上交付字节或数据报TCP、UDP、QUIC字节代表什么业务操作
如何表达请求、响应和浏览器连接HTTP/2、HTTP/3、WebSocket、WebTransport重试是否会重复修改业务状态
如何建立并维持实时会话WebRTC 协议栈应用自己的用户、房间与权限逻辑
如何调用远端方法或分发消息gRPC、MQTT、DDS、CoAP所有外部副作用是否已经完成

这里的分组是为了区分职责,不是严格的 OSI 层次表。WebRTC 本身是一组协作协议;WebTransport 同时涉及浏览器 API 和线上传输映射;DDS 也不仅仅是一个报文格式。

先把这些边界分开,后面才能看清:新协议究竟修正了哪个旧问题,又把哪些问题留给了应用。

从丢包开始:可靠传输需要付出什么

先保证正确,再考虑速度

白板要上传一个文件。最简单的办法是发出一块数据,然后等接收端回复“收到了”,再发下一块。

但如果没有等到回复,发送端不能立即断定数据丢了:数据可能没到,也可能已经到达,只是确认丢了。于是我们需要给数据编号,让接收端能识别重复内容;还需要超时或其他丢包判断机制,在必要时补发。接收端再根据编号整理顺序,才能向应用交付完整内容。TCP 将这些工作组织成可靠、有序的 byte stream;一次应用写入并不对应接收端的一次读取,应用还要自己定义消息边界。(Kao, n.d.)

这里的“可靠”不是承诺网络永远可用。连接最终仍可能失败;协议做的是检测缺口、尝试恢复,并在成功的连接上提供约定的交付语义。

等一个确认再发下一块虽然容易理解,却可能浪费绝大部分链路容量。假设:

  • 每块有效数据为 1200 bytes;
  • 往返时间 R=80ms
  • 瓶颈链路速率 C=24Mbit/s=3MB/s

暂时忽略头部和发送这一小块数据本身的时间,每轮只能交付 1200 bytes,速率大约是

12000.08=15000 bytes/s.

链路每秒本来可以传约 3 MB,我们却只用了约 0.5%

浪费发生在等待期间:前一块数据还在路上,后面的数据已经可以出发。要让链路在一次往返中持续工作,就需要同时容纳大约“一次往返期间能够发出去的数据量”:

WCR=3×106×0.08=240000 bytes.

这就是 bandwidth-delay product 在这个简化场景中的含义。窗口允许多个尚未确认的数据块同时在途,而不是把每次发送都变成一次完整的来回等待。它给出的是量级直觉,不是实际连接只要设置成 240 kB 就一定跑满的保证。

不能只问“还能发多少”

允许更多数据在途后,又出现两个不同的限制。

接收端可能来不及处理数据,自己的缓冲区快满了。它需要通过 flow control 告诉发送端还有多少接收空间。(Kao, n.d.) 即使接收端内存很大,中间链路也可能已经拥堵;发送端还需要通过 congestion control 调整进入网络的数据量。(Kao, n.d.a) 前者保护接收端,后者保护路径。

如果在已经饱和的瓶颈前多堆 600 kB,而出口仍是 3 MB/s,这批积压就会额外引入约

6000003×106=0.2 s

的排队等待。更多缓冲并没有让链路变快,只是让数据更晚到达。

这也解释了为什么实时通信不能简单地把拥塞控制关掉:发送得越积极,可能越是在替未来的语音积累延迟。

HTTP/2 到 QUIC:不要让无关的请求一起等待

打开白板页面时,浏览器可能同时请求样式、脚本和缩略图。它们不必全部依次完成。

HTTP/2 可以把不同请求的内容切成 frame,用 stream ID 区分,再交错放进同一条连接。例如,先发送脚本的一部分,再发送缩略图的一部分。应用层因此可以并发处理多个请求,不再要求把一个响应全部发完后才开始下一个。(Thomson & Benfield, 2022)

问题是:HTTP/2 通常把这些 frame 放进同一条 TCP byte stream。假设顺序是 A1,A2,B1,其中 A 是脚本,B 是缩略图。若 A1 对应的数据丢了,虽然 A2B1 已经到达,TCP 仍不能越过缺口把后面的字节交给 HTTP/2。

TCP 并不知道 B1 属于一个独立请求;它承诺交付的,是一条有序字节流。于是一个请求的丢包,会挡住另一个请求已经到达的数据。这是这里关心的 head-of-line blocking。

同一个丢包,在 TCP 与 QUIC 中阻塞不同的交付范围两个流分别有 A1、A2 和 B1 三段数据。A1 丢失,A2 与 B1 已到达。HTTP/2 的这些数据共用一个 TCP byte stream,A1 形成的缺口让后面的 A2 与 B1 都不能交给 HTTP/2。QUIC 按流分别交付,A2 仍等待 A1,而 B1 可以交付。各条 QUIC 流仍共享连接级拥塞控制。HTTP/2 over TCP丢失A1已到达A2已到达B1QUIC丢失A1已到达A2已到达B1一个有序 TCP byte streamA1A2B1缺口未补齐A2、B1 都暂不能交付每条 stream 分别按序交付AA1A2A2 仍等待 A1BB1B1 可以交付独立交付 ≠ 独立带宽:QUIC 的各条流仍共享连接级 congestion control
图中每个包只承载一条 stream 的一段数据,且 A1 位于 TCP byte stream 的较早位置。比较的是 A2、B1 已经到达之后,谁能交付给上层;不是谁先到达。QUIC 消除的是跨 stream 的这种 head-of-line blocking,同一 stream 内的缺口仍要等待补齐,共享拥塞也仍会影响各条流。

QUIC 把可靠性放回每条 stream

要解除这种牵连,光在 TCP 上再加一个 stream ID 不够:TCP 的交付接口已经要求所有字节按序出现。我们需要让传输层直接认识多条 stream。

QUIC 让每条 stream 有自己的字节偏移和交付顺序。收到 B1 后,只要 B 自己前面没有缺口,就可以交付它;A2 则继续等待 A1。这并不是把所有内容都变成“不可靠发送”,而是把可靠、有序交付的范围从整条连接缩小到各条 stream。(Iyengar & Thomson, 2021)

这种独立性也有边界。不同 stream 仍共享连接级拥塞控制;一个 QUIC packet 也可以携带多条 stream 的数据,丢掉它可能同时影响多条 stream。某条 stream 内部的缺口,仍然会阻塞这条 stream 后续字节的有序交付。(Iyengar & Swett, 2021; Iyengar & Thomson, 2021)

QUIC 使用 UDP 承载,但可靠性不是 UDP 提供的。确认、丢包检测、重传、流量控制和拥塞控制都由 QUIC 自己实现。使用 UDP 的一个工程价值,是让新的传输逻辑可以随端点软件演进,而不必首先把一种新的传输层协议部署到整条互联网路径。它并不意味着 QUIC 不受网络限制:UDP 被阻断时,HTTP 客户端仍需要尝试基于 TCP 的 HTTP。(Bishop, 2022; ETH Networked Systems Group, 2025)

为什么 QUIC 还要把 packet number 和 stream offset 分开?

假设 packet 17 携带 stream A 的第 0999 字节,随后丢失。补发时,相同的字节范围可以装入 packet 23。stream offset 表示“这是内容的哪个位置”,packet number 表示“这是哪一次发包”。

因此,ACK 确认 packet 23 时,发送端能知道被确认的是后一次发送,而不是含糊地猜测原包还是重传包到达了。QUIC 的恢复过程重新发送仍然需要的信息,不要求原封不动重发整个旧包。packet number 在各自的编号空间内不复用;stream offset 则继续描述原来的逻辑字节位置。(Iyengar & Swett, 2021; Iyengar & Thomson, 2021)

少一次等待,还要处理握手和移动网络

传数据之前,双方通常还要确认协议参数并建立加密密钥。QUIC 把 TLS 1.3 握手整合进连接建立过程;在普通、无额外 Retry 的首次握手中,客户端可在一次往返后开始发送应用数据。曾经连接过的客户端,在满足恢复条件时还可以尝试 0-RTT,把早期数据放进首次发出的数据包。(Thomson & Turner, 2021)

但 0-RTT 不是“所有连接都没有握手开销”。它依赖此前获得的状态,服务端也可以拒绝早期数据;更重要的是,早期数据存在 replay 风险。把“查询白板列表”和“新建一次扣费操作”同样放进可重放请求里,后果显然不同。能否使用 0-RTT,需要应用参与判断。(Thomson & Turner, 2021)

移动设备还有另一个问题:从 Wi-Fi 切换到移动网络后,IP 地址和端口可能变化。QUIC 用 connection ID 帮助识别连接,使连接不必只绑定在原来的地址组合上。不过,新路径仍需验证,端点也必须保留连接状态并允许相应迁移;connection ID 并不保证任意断网都能无缝恢复。(Iyengar & Thomson, 2021)

HTTP/3 改变承载方式,不改变“请求一个资源”

有了 QUIC,HTTP/3 就可以把一次请求和响应放到一条双向 QUIC stream 上。HTTP 的方法、状态码和资源语义没有因此变成另一套东西,改变的是这些语义如何在线上传输。(Bishop, 2022)

“QUIC 已经独立分流”也不等于 HTTP/3 完全没有等待。为了压缩 header,QPACK 可以引用动态表中的条目;如果解码某个 header 所需的表更新还没到,它仍可能被阻塞。这是压缩状态的依赖,不是 TCP 字节流的缺口。(Bishop, 2022)

所以,更准确的结论是:QUIC 拆开了一类原本不必要的交付依赖,而不是消灭了一切依赖,也不是保证任何网络、任何负载下都比 TCP 更快。

实时通信:正确的数据也可能已经失去价值

文件下载的自然目标是最终拿到完整文件。但在白板语音里,假设一句话中的一个音频包迟到了两秒:它的字节即使完全正确,也通常不应该插回当前正在播放的句子。

这里出现了与可靠性不同的维度:数据什么时候失效?

先看一个具体例子。每个音频包包含 20 ms 的声音,攒够这一帧需要 20 ms,编码再花 5 ms。用一条理想的共同时间轴表示时间,五个包如下;单位均为 ms。

帧首样本产生 ti开始发送 si=ti+25网络耗时 ni到达 ri=si+ni
10253257
220453883
340652994
4608561146
58010534139

第 5 包甚至比第 4 包先到。如果收到一个包就立刻播放,声音会忽快忽慢,还可能乱序。接收端需要按照媒体时间安排播放,并用 jitter buffer 吸收一部分到达波动。RTP 为媒体提供序号和时间戳:序号帮助识别丢失与乱序,时间戳表达媒体采样时间,而不是简单记录这个包的发送墙钟。(Schulzrinne et al., 2003)

多等一点,究竟换来了什么

我们给每个包设定相同的预算 P:从开始发送,到必须从缓冲区释放给解码器,最多等这么久。释放时刻就是

qi=si+P.

包必须在这个时刻之前到达。把 ri=si+ni 代进去,就得到条件 niP

如果 P=45 ms,第 4 包本应在 85+45=130 ms 释放,却直到 146 ms 才到,迟了 16 ms。如果把 P 增加到 65 ms,这五个包就都赶得上。代价是:所有声音都晚了 20 ms。

这里容易混淆“预算”和“实际缓冲时间”。一个按时到达的包,在接收端真正等待的是

bi=qiri=Pni.

网络花得越久,留给缓冲区的等待就越少。假设解码和播放还要 5 ms,帧首样本到被听见的总延迟是

L=20+5+P+5,

也就是 7595 ms。不能再在这个式子里加一次平均网络耗时,因为 P 已经包含它了。实际系统还要估计时钟关系、适应不断变化的网络;这个五包算例只展示预算的含义,并不保证未来的包也能赶上。

来得及的时候,重传仍然有用

“实时”并不意味着所有包都禁止重传。如果离播放还有足够时间,补回一个丢包可能很值得;来不及重传时,可以利用此前发送、且已及时到达的纠错冗余恢复内容,或者由解码器估计缺失的声音。这分别是前向纠错(FEC)和丢包隐藏的思路。冗余需要提前发送,会消耗额外带宽,也可能增加等待;这些办法都无效时,就只能放弃过时内容。(Perkins et al., 2021)

视频还存在帧间依赖,丢掉一个重要参考帧可能影响后续多帧,因此不能仅凭“这个包比较旧”决定它没有价值。编码依赖可以结合多媒体压缩中的视频部分理解。

缓冲也只能吸收短期波动,不能解决持续超载。假设编码器每秒产生 3 Mbit,链路却只能送出 2 Mbit;持续 200 ms 后就积压 0.2 Mbit,仅这些积压就要花 100 ms 才能从瓶颈排出去。继续把每一帧保留下来,只会让通话越来越滞后。实时系统因此需要根据反馈减少新内容的产生速率,而不只是让旧内容慢慢排队。(Perkins et al., 2021)

WebRTC:实时会话不仅仅是一条 UDP 连接

即使已经理解媒体时限,两个浏览器也不能直接开始通话。它们还要知道对方支持什么格式、去哪里发送数据,以及如何建立安全连接。

先找到彼此,再确认路径真的可达

白板应用首先通过自己的服务交换用 SDP 表达的会话描述和相关连接信息,例如支持的媒体格式、ICE 凭据和证书指纹。这个过程叫 signaling,可以使用 HTTPS 或 WebSocket 等机制;WebRTC 不替应用规定用户怎样登录、怎样进入房间,也不规定必须使用哪一种 signaling 协议。(Alvestrand, 2021)

接下来,地址本身还可能不够。家庭路由器等设备常通过 NAT 在私网和外网之间转换地址,浏览器看到的私网地址不一定能被对方访问。因此,需要收集和验证几种可能的联系路径:

  • 本地地址形成 host candidate。
  • STUN 可以让端点得知服务器观察到的映射地址,形成 server-reflexive candidate。
  • TURN 可以分配 relay candidate,让数据经中继转发。

这些 candidate 只是可能可达的地址,不是可达性的保证。ICE 将两端候选配对并执行连接检查,再通过提名过程选用有效路径;不是拿到一个公网地址就自动打通所有 NAT。(Keranen et al., 2018)

WebRTC 的 signaling 与候选媒体路径是不同的连接两个浏览器通过应用自己的 signaling 服务交换会话描述和 ICE candidates。ICE 检查候选路径;可选择浏览器间直接传输,也可选择经过 TURN relay 的路径。两种媒体路径是替代选项,不是先经过直连再经过 TURN 的串联步骤。虚线表示 signaling,实线表示直接媒体路径,点划线表示 TURN 中继路径。Signaling server由应用选择和实现交换 SDP 与 ICE candidates浏览器 AICE candidates本地 / 映射 / 中继浏览器 BICE candidates本地 / 映射 / 中继可选路径 ①:直连SRTP / DataChannel可选路径 ②:TURN 中继TURN relay为端点分配 relay addressICE 选择可达的 candidate pair;signaling 的通路与媒体的通路不必相同
虚线是 signaling,实线是直连,点划线是 TURN 中继。两种媒体路径是备选关系, 不是串联步骤,也不表示必须同时传输;媒体不必经过 signaling server。

TURN 也不是失败后才神奇出现的一条必通隧道:中继服务需要部署、鉴权和带宽,网络策略仍可能阻断连接。WebRTC 的传输要求还考虑了 UDP 不可用时的 TCP/TLS 中继路径,因此“WebRTC 永远只走 UDP”并不准确。(Alvestrand, 2021b)

路径、加密与媒体分别承担什么

路径建立后,双方通过 DTLS 握手建立密钥材料。握手中的证书还要与会话描述中的指纹匹配;因此,身份保证也依赖 signaling 或其他身份验证机制对指纹的可信绑定。(Rescorla, 2021) WebRTC 媒体必须由 SRTP/SRTCP 保护;DataChannel 则使用 SCTP over DTLS。这里不是把所有 RTP 包都塞进 DTLS 的应用数据记录中,而是使用 DTLS 导出的密钥保护媒体包。(Alvestrand, 2021b)

RTP 承担媒体序号和时间戳等信息,RTCP 提供相关反馈;真正把声音连续播出来,还要依靠编解码、缓冲、丢包恢复和拥塞适应。WebRTC 的价值正在于把这些机制组织成能够互通的实时通信体系,而不只是提供一个发送 UDP 的 API。(Perkins et al., 2021)

多人会议还常使用 SFU:每个参与者把媒体发给服务器,由服务器选择性转发给其他参与者。这与 TURN 的通用中继角色不同。SFU 即使只转发而不解码视频,也不代表它默认无法解密媒体;如果希望媒体内容对转发服务器保持不可见,需要额外的端到端内容保护,例如 SFrame,并确保 SFU 不持有相应内容密钥。密钥分发与成员权限仍需要应用设计,转发所需的部分元数据也不因此隐藏。(Omara et al., 2024)

DataChannel:可靠和有序是两个旋钮

语音之外,白板还要传光标和绘图数据。WebRTC DataChannel 提供有消息边界的数据传输,并允许配置顺序和可靠性。可靠、有序适合必须完整交付的内容;无序、限制重传的配置则适合某些时效性更新。无序不等于不可靠:是否等待先前消息,与是否努力补回丢失消息,是两个问题。(Jesup et al., 2021)

但应用的数据表示必须配合这种选择。

若每条光标消息都是“当前位置为 (x,y),序号为 k”,接收端可以保留最新序号,忽略迟到的旧位置。若消息却是“向右移动 3 像素”,少一次更新就会积累误差。相同的不可靠通道,对绝对状态和增量操作会产生完全不同的结果。

同理,白板上的持久笔画不能因为“也是实时数据”就随便丢弃。它可以使用可靠传输,也可以由应用设计版本、确认和补同步机制;可靠性必须在某一层真正落实。

WebTransport:对端是服务器时,还需要什么

如果光标、游戏状态或协作数据本来就要经过服务器,那么应用未必需要整套对等媒体会话机制。它可能只想在同一个会话里同时拥有可靠 stream 和不可靠 datagram。

这正是 WebTransport 适合讨论的地方:它面向客户端与服务器通信,提供不同的传输原语,但不会自动替应用完成音频采集、编解码和播放。stream 提供可靠、有序的字节序列,消息边界仍由应用定义;datagram 保留每条数据报的边界,但不保证到达或顺序。通过 HTTP/3 的映射,它可以使用 QUIC 的能力。(Frindell et al., 2026; World Wide Web Consortium, 2026)

标准状态也要与机制分开看:截至本文写作日 2026 年 9 月 22 日,WebTransport API 已有 2026 年 7 月的 W3C Candidate Recommendation Snapshot,而 HTTP/3 映射仍是 IETF draft,并非已经发布的 RFC。理解其设计,不等于假设所有客户端、服务器和代理都支持相同部署组合。(Frindell et al., 2026; World Wide Web Consortium, 2026)

为什么有了可靠 stream,还需要 datagram

考虑白板每隔一小段时间发送一次完整光标位置。若第 41 次更新丢失,第 42 次已经到达,接收端通常希望立即使用第 42 次,而不是等第 41 次补齐。

可靠 stream 的字节交付语义并不允许随意跳过缺口;QUIC DATAGRAM 扩展则允许发送不进行传输层重传的数据。应用需要自行定义消息内容、序号和新鲜度规则。它仍受拥塞控制约束,也受数据报大小限制:不可靠的含义是“这条内容可以不补发”,不是“可以无限速、无限大地发送”。(Pauly et al., 2022)

对同一个协作会话,可以把持久编辑操作放到可靠 stream,把能被后续完整状态取代的光标位置放到 datagram。这样做并不是给后者更低的业务地位,而是承认两类数据的有效期不同。

与 WebSocket、SSE 怎样区分

接口最自然的交互方式选择时先问什么
SSE / EventSource服务器持续向浏览器发送文本事件是否只需要服务端推送?
WebSocket双向、有消息边界的连接是否需要一个简单的双向可靠消息通道?
WebTransport客户端与服务器之间的多条 stream 与 datagram是否真的需要区分完整交付和过时可丢?
WebRTC实时媒体会话与 DataChannel是否需要媒体处理、候选路径发现或端点间连接?

SSE 的自动重连和事件 ID 不会自动让服务器拥有永久事件历史。(WHATWG, n.d.) WebSocket 的经典映射建立在 TCP 上;后来也有 HTTP/2、HTTP/3 的承载方式,但单个 WebSocket 仍不因此变成多 stream 加不可靠 datagram 的接口。(Fette & Melnikov, 2011; Hamilton, 2022; McManus, 2018) 这些接口的选择应从交互模型出发,而不只是比较新旧。

MoQ 又在增加哪一层?

能发送媒体字节,还不等于适合把直播分发给大量订阅者。应用还需要表达“这是什么内容”“订阅哪一部分”“中继优先转发什么”。Media over QUIC(MoQ)探索的是这一层的发布订阅与媒体分发机制,可以利用 QUIC 或 WebTransport,而不是另造一个替代 UDP 的底层协议。

截至 2026 年 9 月 22 日,MoQ Transport 仍在 IETF draft 阶段。它适合用来理解设计趋势;讨论具体对象格式、优先级和恢复语义时,应固定草案版本,不能把变化中的细节写成既定标准。(Nandakumar et al., 2026)

gRPC:字节送到了,操作就完成了吗

白板保存服务已经有了一条可靠连接,为什么还需要 RPC?

因为字节本身没有告诉服务器:应该调用哪个方法、参数怎么解析、响应属于哪个请求。RPC 把这些约定组织成“调用远端方法”的接口。gRPC 通常用 Protocol Buffers 定义服务和消息,再生成客户端 stub 与服务端接口;RPC 是抽象,gRPC 是框架和协议机制,Protobuf 是默认采用的描述与编码工具,三者并不是同一个东西。(The gRPC Authors, n.d.)

例如,一次保存操作可以表达为 SaveBoard(board_id, revision, operations),而不必让每个调用者手工拼接和解析字节。gRPC 还支持单次请求响应、服务端流、客户端流和双向流。但接口像本地函数,不代表远端失败也能像本地函数一样判断。(The gRPC Authors, n.d.)

一次超时,至少有几种不同的过去

假设我们的协作产品还有一个简化的内部余额系统。客户端请求扣除 100,原余额为 500。如果没有收到响应,可能发生了什么?

  1. 请求根本没到服务器,余额仍是 500
  2. 请求到了,但服务器在提交前失败,余额仍是 500
  3. 服务器已经提交扣款,余额变成 400,但成功响应没有到达客户端。

客户端看见的都可能只是 timeout。可靠传输不会自动区分这三种业务历史;超时也不是“操作没有发生”的证明。(MIT 6.5840 Course Staff, 2026)

如果客户端直接重试“再减 100”,第三种情况就会把余额变成 300。要修正它,先要让服务器分清:这是一次新的业务意图,还是对同一次意图的重复尝试?

先给业务意图命名,再让提交原子化

客户端可以给这次操作生成稳定的 operation_id,例如图中的 42,重试时继续使用它。服务端看到这个 ID 已经完成,就返回原来的结果,不再重复扣款。

但只在扣款后向内存集合里记一个 ID 还不够:如果恰好在扣款成功、记录 ID 之前崩溃,重启后仍然无法识别重试。于是,在这个所有账本状态都位于同一数据库的简化系统中,我们要把下面几件事放进同一事务:

  • 通过唯一约束等机制占用操作 ID,并处理并发重复请求;
  • 核对同一 ID 对应的请求参数,拒绝“同一 ID、不同金额”;
  • 修改余额;
  • 保存本次结果,以便重试时返回。

这样,提交成功意味着业务修改和去重结果一起存在;没有提交,则不应留下已经生效的半次修改。这里得到的是“重复请求不产生额外业务效果”,而不是让网络神奇地只传一次。(Featonby, n.d.)

RPC 响应丢失时,用相同 operation ID 查询已经提交的结果客户端发出 operation ID 为 42 的请求。服务端在同一个数据库事务中提交业务效果和 operation ID 到结果的记录,但响应丢失。客户端超时后不能判断操作是否执行;它携带相同 ID 重试。服务端命中已提交的记录,返回原结果而不重复业务效果。时间向下。ClientService + transactional DB时间1. request · op=42同一个事务中 commit业务效果op=42 → result2. response 丢失timeout:结果未知3. retry · op=42命中已提交的 ID核对参数,读取原结果不重复业务效果4. 返回原 result同一业务操作重用同一 ID;去重记录的保留期也是协议契约的一部分
图中展示“已经提交,但响应丢失”的情形。客户端复用同一操作 ID 重试,服务端读取原结果; timeout 本身并不能告诉客户端此前是否已经提交。

这个设计还有明确的适用边界:去重记录需要保留策略;永久失联时不能保证最终完成;如果真实扣款发生在另一个外部支付服务,本地数据库事务就不能包住远端副作用,还需要远端支持相同的幂等键或额外协调。不要把一个本地事务例子直接升级成对所有分布式系统的 exactly-once 承诺。(Featonby, n.d.)

Deadline 和 retry 是预算,不是结果证明

调用还需要 deadline,防止客户端已经放弃后,下游仍无止境地消耗资源。(The gRPC Authors, n.d.b) 取消通常需要应用处理逻辑配合;它不等于回滚已经发生的修改,也不意味着客户端超时的瞬间服务器就必然停止。(The gRPC Authors, n.d.a)

重试同样必须有边界。gRPC 的透明重试针对框架能判断应用尚未处理等有限情形;一般重试策略需要配置可重试状态、次数和退避,不能把“框架支持 retry”理解成所有方法都可以安全重跑。一个非幂等业务方法,仍然需要前面那样的业务契约。(The gRPC Authors, n.d.d)

现在可以把几个“确认”分开:transport ACK 说明某些传输数据到达;RPC 响应可以报告方法的结果;业务是否持久生效,则取决于服务端怎样定义成功并提交状态。它们可能接近发生,但不是同一件事。

发布订阅:如果发送者不该认识每个接收者

RPC 很适合“请这个服务执行这个操作”。但另一类问题是:“这里发生了一次更新,谁关心谁来接收。”

例如,一个温度传感器的读数同时被仪表盘、空调和告警系统使用。如果传感器逐个调用它们,就需要维护每个消费者的地址和失败状态。发布订阅把接收者管理从生产者中分离:生产者发布数据,消费者声明兴趣,由中间层负责匹配和分发。

MQTT:消息的确认有明确范围

MQTT 使用 broker 和 topic 组织这种交互。传感器向 building/room-3/temperature 发布,消费者订阅相关主题;发布者不必逐个认识所有订阅者。它不是只能单向通信,每个客户端都可以承担发布与订阅角色。(Jain, 2021)

接下来仍然要问丢包和重复。MQTT 用不同 QoS 等级规定发送者与接收者之间的交付机制:

QoS主要流程协议交付语义
0PUBLISH至多一次,可能没有收到
1PUBLISH → PUBACK至少一次,可能重复
2PUBLISH → PUBREC → PUBREL → PUBCOMP在规定范围内恰好一次交付

这个范围是一个发送者到一个接收者。发布端到 broker、broker 到每位订阅者,是分别处理的交付过程,使用的 QoS 也可能不同。收到发布端的协议确认,不能推出所有订阅者已经各自完成了一次数据库更新。QoS 2 的去重状态同样不会自动与消费者的业务事务合并。(OASIS, 2019)

因此,不能用“这里用了 QoS 2”替代对端到端处理语义的设计。对于温度显示,重要的可能是当前值;对于收费事件,重要的则是持久记录和业务去重,即使二者都被装进 MQTT 消息。

DDS:可靠性之外,还要描述数据多久有用

机器人每 10 ms 发布一次位置。一次网络抖动持续了 200 ms,恢复后,控制器是希望逐个消费积压的约 20 个旧位置,还是尽快拿到最新位置?

仅仅选择“可靠”还不能回答这个问题。我们还需要分别表达保留多少历史、样本何时过期,以及晚加入的接收者要不要得到此前的数据。

DDS 围绕带类型的数据和发布订阅关系组织通信,提供相应 QoS 策略;RTPS 则规定了 DDS 实现之间使用的一种互操作线协议。讨论 ROS 2 时也要分清:ROS 2 的中间件抽象并不等同于 DDS 标准本身。(Elwin, n.d.; Object Management Group, 2022)

以常见 QoS 名称为例,Reliability 关心尽力交付还是可靠交付,History 关心保留多少样本,Lifespan 关心样本有效期。Deadline 表达预期的更新间隔和违约检测,不是让网络自动保证所有数据准时到达。发送端提供的策略还需要满足接收端请求的兼容条件,并非两边所有配置必须字面相同。(ROS 2 Documentation Contributors, n.d.)

这里真正值得记住的不是策略名称,而是这些维度不能压缩成同一个“可靠性等级”。

CoAP:收到消息和完成请求可以显式分开

受限设备也可能需要“读取温度资源”“修改目标温度”这样的资源操作。CoAP 把这类请求响应语义带到受限网络环境,其基础 UDP 映射区分可确认与不可确认消息。

一个很能说明边界的设计是:服务端可以先发送空 ACK,表示消息收到,等操作完成后再单独发送响应。空 ACK 不是“温度已经设置成功”。(Shelby et al., 2014)

CoAP Observe 则允许客户端持续接收资源状态变化通知。它关心观察者跟上当前状态,不保证每个中间状态都成为不可遗漏的事件日志。因此,“观察当前温度”和“保存每笔交易”不能只因为都需要推送,就采用完全相同的交付假设。(Hartke, 2015)

回到白板:把协议组合起来

现在重新设计开头的在线白板,不需要先选一个包办全部通信的协议。可以按数据的含义拆开选择。

数据或操作需要保持的性质可以采用的组合与额外设计
页面、图片、文件内容完整,允许一定等待HTTP/2 或 HTTP/3;恢复与缓存按应用需求设计
语音与视频在播放时限内尽量连续WebRTC 媒体链路、拥塞适应、缓冲与丢包恢复
完整光标位置优先新状态,旧状态可以失效DataChannel 或 WebTransport datagram,加序号与过期判断
持久白板操作编辑不能静默丢失可靠通道,加版本、确认、重连后的补同步
后端扣费或保存方法可报告结果,重试不误执行RPC 加 deadline、操作 ID 和明确的事务边界
面向多个消费者的状态更新发送者与消费者解耦MQTT 或 DDS,按状态有效期和业务需求选择 QoS

这张表不是唯一架构。一个较简单的产品,完全可能用 HTTP 加 WebSocket 完成大部分功能;只有在确实需要媒体链路、独立 stream 或过时可丢的数据时,引入额外机制才有清晰收益。

选择之前,可以沿着同一条顺序追问:数据是完整文件、增量操作,还是可覆盖的状态?缺了前一条,后一条还能不能独立使用?晚到是否仍有价值?超时之后,远端可能已经做了什么?确认停在哪个边界?

QUIC 让独立的数据流不必因为别人的缺口一起等待;实时协议让数据的时间价值进入设计;RPC 和消息协议让通信拥有操作与分发语义。但应用最终仍要定义:什么必须被保留,什么可以过期,什么效果不能重复发生。

继续阅读

如果希望沿着本文的推导补齐基础,可以先读 Berkeley CS 168 的 TCP 设计(Kao, n.d.b) 接着补齐拥塞控制,再进入下面几组材料。(Kao, n.d.a) 课程用于建立整体理解,具体线协议和安全性质则应与对应版本的标准一起阅读。

方向课程或教材适合带着什么问题读
QUIC 与传输演进ETH Zürich Advanced Topics in Communication Networks,2025 年 transport 课件;Stanford CS 249I 的 Web Protocol Evolution为什么 HTTP 多路复用还需要传输层配合?握手与部署分别限制了什么?
实时媒体UCSB CS 176C,Spring 2026 Lecture 12;WebRTC for the Curious如何分配播放预算?发现地址、验证路径、保护媒体为何是不同步骤?
RPC 与失败MIT 6.5840,2026 年 Threads and RPC;Cornell CS 4414 的 networking slides为什么一次超时不能证明远端没有执行?接口抽象隐藏了什么?
物联网与机器人Washington University in St. Louis 的 MQTT 讲义;Northwestern ME495 的 DDS notes消费者是谁来管理?可靠性、历史与有效期怎样分别表达?

ETH 的 2025 年课件适合连接传统 transport 与 QUIC。(ETH Networked Systems Group, 2025) Stanford 的材料适合看 Web 协议演进,不过其中 QUIC 握手部分包含早期设计,理解现代 IETF QUIC 时应以 RFC 9000/9001 为准。(Durumeric, 2025)

实时媒体可以先读 UCSB 的场景导向讲解。(Gupta, 2026) 再读 WebRTC for the Curious 的 connecting、securing、media communication 和 data communication 章节。(WebRTC for the Curious Contributors, n.d.) 涉及延迟计算时,始终先确认每个时间量的起止点。

MIT 的 RPC notes 值得完整阅读。(MIT 6.5840 Course Staff, 2026) Cornell 的 gRPC 部分更适合作为短简介,引用的是 2024 年秋季课程提供的 Spring 2023 课件。(Birman, 2023) MQTT 的课程材料采用 2021 年版本,具体 QoS 行为对照 MQTT 5.0。(Jain, 2021) Northwestern 的 DDS notes 则可以结合 ROS 2 的 QoS 配置,继续研究发布端和订阅端如何匹配。(Elwin, n.d.)

References

Alvestrand, H. (2021a). Overview: Real-Time Protocols for Browser-Based Applications (Techreport RFC 8825). Internet Engineering Task Force. doi.org
Alvestrand, H. (2021b). Transports for WebRTC (Techreport RFC 8835). Internet Engineering Task Force. doi.org
Birman, K. (2023). Networking. Cornell University, CS 4414 Systems Programming. cs.cornell.edu
Bishop, M. (2022). HTTP/3 (Techreport RFC 9114). Internet Engineering Task Force. doi.org
Durumeric, Z. (2025). Web Protocol Evolution. Stanford University, CS 249i The Modern Internet. cs249i.stanford.edu
Elwin, M. (n.d.). Data Distribution Service (DDS). Northwestern University, ME 495 Embedded Systems in Robotics. nu-msr.github.io
ETH Networked Systems Group. (2025). Advanced Topics in Communication Networks. ETH Zurich. polybox.ethz.ch
Featonby, M. (n.d.). Making Retries Safe with Idempotent APIs. The Amazon Builders’ Library. aws.amazon.com
Fette, I., & Melnikov, A. (2011). The WebSocket Protocol (Techreport RFC 6455). Internet Engineering Task Force. doi.org
Frindell, A., Kinnear, E., & Vasiliev, V. (2026). WebTransport over HTTP/3 (Techreport draft-ietf-webtrans-http3-16). Internet Engineering Task Force. datatracker.ietf.org
Gupta, A. (2026). When Buffering Is Forbidden: VoIP, Jitter, and Modern Real-Time. University of California, Santa Barbara, CS 176C. sites.cs.ucsb.edu
Hamilton, R. (2022). Bootstrapping WebSockets with HTTP/3 (Techreport RFC 9220). Internet Engineering Task Force. doi.org
Hartke, K. (2015). Observing Resources in the Constrained Application Protocol (CoAP) (Techreport RFC 7641). Internet Engineering Task Force. doi.org
Iyengar, J., & Swett, I. (2021). QUIC Loss Detection and Congestion Control (Techreport RFC 9002). Internet Engineering Task Force. doi.org
Iyengar, J., & Thomson, M. (2021). QUIC: A UDP-Based Multiplexed and Secure Transport (Techreport RFC 9000). Internet Engineering Task Force. doi.org
Jain, R. (2021). Messaging Protocols for Internet of Things: MQTT. Washington University in St. Louis, CSE 570S Recent Advances in Networking. cs.wustl.edu
Jesup, R., Loreto, S., & Tüxen, M. (2021). WebRTC Data Channels (Techreport RFC 8831). Internet Engineering Task Force. doi.org
Kao, P. (n.d.a). Congestion Control Principles. University of California, Berkeley, CS 168 course textbook. textbook.cs168.io
Kao, P. (n.d.b). TCP Design. University of California, Berkeley, CS 168 course textbook. textbook.cs168.io
Keranen, A., Holmberg, C., & Rosenberg, J. (2018). Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal (Techreport RFC 8445). Internet Engineering Task Force. doi.org
McManus, P. (2018). Bootstrapping WebSockets with HTTP/2 (Techreport RFC 8441). Internet Engineering Task Force. doi.org
MIT 6.5840 Course Staff. (2026). 6.5840 2026 Lecture 2: Threads and RPC. Massachusetts Institute of Technology, 6.5840 Distributed Systems. pdos.csail.mit.edu
Nandakumar, S., Vasiliev, V., Swett, I., & Frindell, A. (2026). Media over QUIC Transport (Techreport draft-ietf-moq-transport-21). Internet Engineering Task Force. datatracker.ietf.org
OASIS. (2019). MQTT Version 5.0 (A. Banks, E. Briggs, K. Borgendale, & R. Gupta, Eds.). OASIS. docs.oasis-open.org
Object Management Group. (2022). DDS Interoperability Wire Protocol (2.5). Object Management Group. omg.org
Omara, E., Uberti, J., Murillo, S. G., Barnes, R., & Fablet, Y. (2024). Secure Frame (SFrame): Lightweight Authenticated Encryption for Real-Time Media (Techreport RFC 9605). Internet Engineering Task Force. doi.org
Pauly, T., Kinnear, E., & Schinazi, D. (2022). An Unreliable Datagram Extension to QUIC (Techreport RFC 9221). Internet Engineering Task Force. doi.org
Perkins, C., Westerlund, M., & Ott, J. (2021). Media Transport and Use of RTP in WebRTC (Techreport RFC 8834). Internet Engineering Task Force. doi.org
Rescorla, E. (2021). WebRTC Security Architecture (Techreport RFC 8827). Internet Engineering Task Force. doi.org
ROS 2 Documentation Contributors. (n.d.). Quality of Service Settings. ROS 2. github.com
Schulzrinne, H., Casner, S., Frederick, R., & Jacobson, V. (2003). RTP: A Transport Protocol for Real-Time Applications (Techreport RFC 3550). Internet Engineering Task Force. doi.org
Shelby, Z., Hartke, K., & Bormann, C. (2014). The Constrained Application Protocol (CoAP) (Techreport RFC 7252). Internet Engineering Task Force. doi.org
The gRPC Authors. (n.d.a). Cancellation. gRPC. grpc.io
The gRPC Authors. (n.d.b). Core Concepts, Architecture and Lifecycle. gRPC. grpc.io
The gRPC Authors. (n.d.c). Deadlines. gRPC. grpc.io
The gRPC Authors. (n.d.d). Retry. gRPC. grpc.io
Thomson, M., & Benfield, C. (2022). HTTP/2 (Techreport RFC 9113). Internet Engineering Task Force. doi.org
Thomson, M., & Turner, S. (2021). Using TLS to Secure QUIC (Techreport RFC 9001). Internet Engineering Task Force. doi.org
WebRTC for the Curious Contributors. (n.d.). WebRTC for the Curious. webrtcforthecurious.com
WHATWG. (n.d.). HTML Standard: Server-Sent Events. WHATWG. html.spec.whatwg.org
World Wide Web Consortium. (2026). WebTransport (N. Jaju, V. Vasiliev, & J.-I. Bruaroey, Eds.). World Wide Web Consortium. w3.org

Cite this post

@misc{pu2026csnotesmoderncommunicationprotocols,
  author = {Pu, Fanyi},
  title  = {现代通信协议:从可靠传输到实时媒体与消息语义},
  year   = {2026},
  month  = {9},
  url    = {https://pufanyi.com/blog/cs/notes/modern-communication-protocols}
}