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

Author: Fanyi Pu

Published: 2026-09-22

Canonical: <https://pufanyi.com/blog/cs/notes/modern-communication-protocols>

从一个在线协作应用出发，理解 TCP、QUIC、HTTP/3、WebRTC、WebTransport、gRPC 与发布订阅协议如何处理丢包、时限和重复执行。

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

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

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

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

本文沿着这三个问题展开：先从 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.](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-berkeleytcp))

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

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

- 每块有效数据为 $1200$ bytes；
- 往返时间 $R=80\,\mathrm{ms}$；
- 瓶颈链路速率 $C=24\,\mathrm{Mbit/s}=3\,\mathrm{MB/s}$。

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

$$
\frac{1200}{0.08}=15000\ \mathrm{bytes/s}.
$$

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

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

$$
W\approx C R=3\times10^6\times0.08=240000\ \mathrm{bytes}.
$$

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

### 不能只问“还能发多少”

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

接收端可能来不及处理数据，自己的缓冲区快满了。它需要通过 **flow control** 告诉发送端还有多少接收空间。([Kao, n.d.](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-berkeleytcp)) 即使接收端内存很大，中间链路也可能已经拥堵；发送端还需要通过 **congestion control** 调整进入网络的数据量。([Kao, n.d.a](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-berkeleycc)) 前者保护接收端，后者保护路径。

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

$$
\frac{600000}{3\times10^6}=0.2\ \mathrm{s}
$$

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

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

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

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

HTTP/2 可以把不同请求的内容切成 frame，用 stream ID 区分，再交错放进同一条连接。例如，先发送脚本的一部分，再发送缩略图的一部分。应用层因此可以并发处理多个请求，不再要求把一个响应全部发完后才开始下一个。([Thomson & Benfield, 2022](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-rfc9113))

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

TCP 并不知道 $B_1$ 属于一个独立请求；它承诺交付的，是一条有序字节流。于是一个请求的丢包，会挡住另一个请求已经到达的数据。这是这里关心的 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

B1

QUIC

一个有序 TCP byte stream

缺口未补齐

A2、B1 都暂不能交付

每条 stream 分别按序交付

A

A2 仍等待 A1

B

B1 可以交付

独立交付 ≠ 独立带宽：QUIC 的各条流仍共享连接级 congestion control

[View diagram in the original article](https://pufanyi.com/blog/cs/notes/modern-communication-protocols)

图中每个包只承载一条 stream 的一段数据，且 A1 位于 TCP byte stream 的较早位置。比较的是 A2、B1 已经到达之后，谁能交付给上层；不是谁先到达。QUIC 消除的是跨 stream 的这种 head-of-line blocking，同一 stream 内的缺口仍要等待补齐，共享拥塞也仍会影响各条流。

### QUIC 把可靠性放回每条 stream

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

QUIC 让每条 stream 有自己的字节偏移和交付顺序。收到 $B_1$ 后，只要 $B$ 自己前面没有缺口，就可以交付它；$A_2$ 则继续等待 $A_1$。这并不是把所有内容都变成“不可靠发送”，而是把可靠、有序交付的范围从整条连接缩小到各条 stream。([Iyengar & Thomson, 2021](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-rfc9000))

这种独立性也有边界。不同 stream 仍共享连接级拥塞控制；一个 QUIC packet 也可以携带多条 stream 的数据，丢掉它可能同时影响多条 stream。某条 stream 内部的缺口，仍然会阻塞这条 stream 后续字节的有序交付。([Iyengar & Swett, 2021](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-rfc9002); [Iyengar & Thomson, 2021](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-rfc9000))

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

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

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

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

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

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

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

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

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

有了 QUIC，HTTP/3 就可以把一次请求和响应放到一条双向 QUIC stream 上。HTTP 的方法、状态码和资源语义没有因此变成另一套东西，改变的是这些语义如何在线上传输。([Bishop, 2022](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-rfc9114))

“QUIC 已经独立分流”也不等于 HTTP/3 完全没有等待。为了压缩 header，QPACK 可以引用动态表中的条目；如果解码某个 header 所需的表更新还没到，它仍可能被阻塞。这是压缩状态的依赖，不是 TCP 字节流的缺口。([Bishop, 2022](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-rfc9114))

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

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

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

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

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

| 包 | 帧首样本产生 $t_i$ | 开始发送 $s_i=t_i+25$ | 网络耗时 $n_i$ | 到达 $r_i=s_i+n_i$ |
| - | ------------ | ----------------- | ---------- | ---------------- |
| 1 | 0            | 25                | 32         | 57               |
| 2 | 20           | 45                | 38         | 83               |
| 3 | 40           | 65                | 29         | 94               |
| 4 | 60           | 85                | 61         | 146              |
| 5 | 80           | 105               | 34         | 139              |

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

### 多等一点，究竟换来了什么

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

$$
q_i=s_i+P.
$$

包必须在这个时刻之前到达。把 $r_i=s_i+n_i$ 代进去，就得到条件 $n_i\le P$。

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

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

$$
b_i=q_i-r_i=P-n_i.
$$

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

$$
L=20+5+P+5,
$$

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

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

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

视频还存在帧间依赖，丢掉一个重要参考帧可能影响后续多帧，因此不能仅凭“这个包比较旧”决定它没有价值。编码依赖可以结合[多媒体压缩中的视频部分](https://pufanyi.com/blog/ml/notes/media-compression)理解。

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

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

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

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

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

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

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

这些 candidate 只是可能可达的地址，不是可达性的保证。ICE 将两端候选配对并执行连接检查，再通过提名过程选用有效路径；不是拿到一个公网地址就自动打通所有 NAT。([Keranen et al., 2018](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-rfc8445))

WebRTC 的 signaling 与候选媒体路径是不同的连接

两个浏览器通过应用自己的 signaling 服务交换会话描述和 ICE candidates。ICE 检查候选路径；可选择浏览器间直接传输，也可选择经过 TURN relay 的路径。两种媒体路径是替代选项，不是先经过直连再经过 TURN 的串联步骤。虚线表示 signaling，实线表示直接媒体路径，点划线表示 TURN 中继路径。

Signaling server

由应用选择和实现

交换 SDP 与 ICE candidates

浏览器 A

ICE candidates

本地 / 映射 / 中继

浏览器 B

可选路径 ①：直连

SRTP / DataChannel

可选路径 ②：TURN 中继

TURN relay

为端点分配 relay address

ICE 选择可达的 candidate pair；signaling 的通路与媒体的通路不必相同

[View diagram in the original article](https://pufanyi.com/blog/cs/notes/modern-communication-protocols)

虚线是 signaling，实线是直连，点划线是 TURN 中继。两种媒体路径是备选关系， 不是串联步骤，也不表示必须同时传输；媒体不必经过 signaling server。

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

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

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

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

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

### DataChannel：可靠和有序是两个旋钮

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

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

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

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

## WebTransport：对端是服务器时，还需要什么

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

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

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

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

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

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

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

### 与 WebSocket、SSE 怎样区分

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

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

MoQ 又在增加哪一层？

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

截至 2026 年 9 月 22 日，MoQ Transport 仍在 IETF draft 阶段。它适合用来理解设计趋势；讨论具体对象格式、优先级和恢复语义时，应固定草案版本，不能把变化中的细节写成既定标准。([Nandakumar et al., 2026](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-moqtransport))

## gRPC：字节送到了，操作就完成了吗

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

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

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

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

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

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

客户端看见的都可能只是 timeout。可靠传输不会自动区分这三种业务历史；超时也不是“操作没有发生”的证明。([MIT 6.5840 Course Staff, 2026](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-mit2026rpc))

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

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

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

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

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

这样，提交成功意味着业务修改和去重结果一起存在；没有提交，则不应留下已经生效的半次修改。这里得到的是“重复请求不产生额外业务效果”，而不是让网络神奇地只传一次。([Featonby, n.d.](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-featonbyidempotent))

RPC 响应丢失时，用相同 operation ID 查询已经提交的结果

客户端发出 operation ID 为 42 的请求。服务端在同一个数据库事务中提交业务效果和 operation ID 到结果的记录，但响应丢失。客户端超时后不能判断操作是否执行；它携带相同 ID 重试。服务端命中已提交的记录，返回原结果而不重复业务效果。时间向下。

Client

Service + transactional DB

时间

1\. request · op=42

同一个事务中 commit

业务效果

op=42 → result

2\. response 丢失

timeout：结果未知

3\. retry · op=42

命中已提交的 ID

核对参数，读取原结果

不重复业务效果

4\. 返回原 result

同一业务操作重用同一 ID；去重记录的保留期也是协议契约的一部分

[View diagram in the original article](https://pufanyi.com/blog/cs/notes/modern-communication-protocols)

图中展示“已经提交，但响应丢失”的情形。客户端复用同一操作 ID 重试，服务端读取原结果； timeout 本身并不能告诉客户端此前是否已经提交。

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

### Deadline 和 retry 是预算，不是结果证明

调用还需要 deadline，防止客户端已经放弃后，下游仍无止境地消耗资源。([The gRPC Authors, n.d.b](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-grpcdeadlines)) 取消通常需要应用处理逻辑配合；它不等于回滚已经发生的修改，也不意味着客户端超时的瞬间服务器就必然停止。([The gRPC Authors, n.d.a](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-grpccancellation))

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

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

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

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

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

### MQTT：消息的确认有明确范围

MQTT 使用 broker 和 topic 组织这种交互。传感器向 `building/room-3/temperature` 发布，消费者订阅相关主题；发布者不必逐个认识所有订阅者。它不是只能单向通信，每个客户端都可以承担发布与订阅角色。([Jain, 2021](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-jain2021mqtt))

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

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

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

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

### DDS：可靠性之外，还要描述数据多久有用

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

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

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

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

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

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

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

一个很能说明边界的设计是：服务端可以先发送空 ACK，表示消息收到，等操作完成后再单独发送响应。空 ACK 不是“温度已经设置成功”。([Shelby et al., 2014](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-rfc7252))

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

## 回到白板：把协议组合起来

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

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

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

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

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

## 继续阅读

如果希望沿着本文的推导补齐基础，可以先读 Berkeley CS 168 的 [TCP 设计](https://textbook.cs168.io/transport/tcp-design.html)。([Kao, n.d.b](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-berkeleytcp)) 接着补齐[拥塞控制](https://textbook.cs168.io/transport/cc-principles.html)，再进入下面几组材料。([Kao, n.d.a](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-berkeleycc)) 课程用于建立整体理解，具体线协议和安全性质则应与对应版本的标准一起阅读。

| 方向         | 课程或教材                                                                                                              | 适合带着什么问题读                           |
| ---------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------- |
| 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](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-eth2025transport)) Stanford 的材料适合看 Web 协议演进，不过其中 QUIC 握手部分包含早期设计，理解现代 IETF QUIC 时应以 RFC 9000/9001 为准。([Durumeric, 2025](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-durumeric2025web))

实时媒体可以先读 UCSB 的场景导向讲解。([Gupta, 2026](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-gupta2026realtime)) 再读 WebRTC for the Curious 的 connecting、securing、media communication 和 data communication 章节。([WebRTC for the Curious Contributors, n.d.](https://pufanyi.com/blog/cs/notes/modern-communication-protocols#bib-webrtccurious)) 涉及延迟计算时，始终先确认每个时间量的起止点。

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

## References

Alvestrand, H. (2021a). *Overview: Real-Time Protocols for Browser-Based Applications* (Techreport RFC 8825). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC8825 "https://doi.org/10.17487/RFC8825")

Alvestrand, H. (2021b). *Transports for WebRTC* (Techreport RFC 8835). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC8835 "https://doi.org/10.17487/RFC8835")

Birman, K. (2023). *Networking*. Cornell University, CS 4414 Systems Programming. [cs.cornell.edu](https://www.cs.cornell.edu/courses/cs4414/2024fa/Slides/20-Networking.pdf "https://www.cs.cornell.edu/courses/cs4414/2024fa/Slides/20-Networking.pdf")

Bishop, M. (2022). *HTTP/3* (Techreport RFC 9114). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC9114 "https://doi.org/10.17487/RFC9114")

Durumeric, Z. (2025). *Web Protocol Evolution*. Stanford University, CS 249i The Modern Internet. [cs249i.stanford.edu](https://cs249i.stanford.edu/lectures/lecture12.pdf "https://cs249i.stanford.edu/lectures/lecture12.pdf")

Elwin, M. (n.d.). *Data Distribution Service (DDS)*. Northwestern University, ME 495 Embedded Systems in Robotics. [nu-msr.github.io](https://nu-msr.github.io/ros_notes/ros2/dds.html "https://nu-msr.github.io/ros_notes/ros2/dds.html")

ETH Networked Systems Group. (2025). *Advanced Topics in Communication Networks*. ETH Zurich. [polybox.ethz.ch](https://www.polybox.ethz.ch/index.php/s/67fnKKJ6QzatDtr/download "https://www.polybox.ethz.ch/index.php/s/67fnKKJ6QzatDtr/download")

Featonby, M. (n.d.). *Making Retries Safe with Idempotent APIs*. The Amazon Builders’ Library. [aws.amazon.com](https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/ "https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/")

Fette, I., & Melnikov, A. (2011). *The WebSocket Protocol* (Techreport RFC 6455). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC6455 "https://doi.org/10.17487/RFC6455")

Frindell, A., Kinnear, E., & Vasiliev, V. (2026). *WebTransport over HTTP/3* (Techreport draft-ietf-webtrans-http3-16). Internet Engineering Task Force. [datatracker.ietf.org](https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3-16 "https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3-16")

Gupta, A. (2026). *When Buffering Is Forbidden: VoIP, Jitter, and Modern Real-Time*. University of California, Santa Barbara, CS 176C. [sites.cs.ucsb.edu](https://sites.cs.ucsb.edu/~arpitgupta/cs176c/spring26/assets/lecture-notes/L12_lecture_notes/ "https://sites.cs.ucsb.edu/~arpitgupta/cs176c/spring26/assets/lecture-notes/L12_lecture_notes/")

Hamilton, R. (2022). *Bootstrapping WebSockets with HTTP/3* (Techreport RFC 9220). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC9220 "https://doi.org/10.17487/RFC9220")

Hartke, K. (2015). *Observing Resources in the Constrained Application Protocol (CoAP)* (Techreport RFC 7641). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC7641 "https://doi.org/10.17487/RFC7641")

Iyengar, J., & Swett, I. (2021). *QUIC Loss Detection and Congestion Control* (Techreport RFC 9002). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC9002 "https://doi.org/10.17487/RFC9002")

Iyengar, J., & Thomson, M. (2021). *QUIC: A UDP-Based Multiplexed and Secure Transport* (Techreport RFC 9000). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC9000 "https://doi.org/10.17487/RFC9000")

Jain, R. (2021). *Messaging Protocols for Internet of Things: MQTT*. Washington University in St. Louis, CSE 570S Recent Advances in Networking. [cs.wustl.edu](https://www.cs.wustl.edu/~jain/cse570-21/ftp/m_13mqtz.pdf "https://www.cs.wustl.edu/~jain/cse570-21/ftp/m_13mqtz.pdf")

Jesup, R., Loreto, S., & Tüxen, M. (2021). *WebRTC Data Channels* (Techreport RFC 8831). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC8831 "https://doi.org/10.17487/RFC8831")

Kao, P. (n.d.a). *Congestion Control Principles*. University of California, Berkeley, CS 168 course textbook. [textbook.cs168.io](https://textbook.cs168.io/transport/cc-principles.html "https://textbook.cs168.io/transport/cc-principles.html")

Kao, P. (n.d.b). *TCP Design*. University of California, Berkeley, CS 168 course textbook. [textbook.cs168.io](https://textbook.cs168.io/transport/tcp-design.html "https://textbook.cs168.io/transport/tcp-design.html")

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](https://doi.org/10.17487/RFC8445 "https://doi.org/10.17487/RFC8445")

McManus, P. (2018). *Bootstrapping WebSockets with HTTP/2* (Techreport RFC 8441). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC8441 "https://doi.org/10.17487/RFC8441")

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](https://pdos.csail.mit.edu/6.824/notes/l-rpc.txt "https://pdos.csail.mit.edu/6.824/notes/l-rpc.txt")

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](https://datatracker.ietf.org/doc/html/draft-ietf-moq-transport-21 "https://datatracker.ietf.org/doc/html/draft-ietf-moq-transport-21")

OASIS. (2019). *MQTT Version 5.0* (A. Banks, E. Briggs, K. Borgendale, & R. Gupta, Eds.). OASIS. [docs.oasis-open.org](https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html "https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html")

Object Management Group. (2022). *DDS Interoperability Wire Protocol* (2.5). Object Management Group. [omg.org](https://www.omg.org/spec/DDSI-RTPS/2.5 "https://www.omg.org/spec/DDSI-RTPS/2.5")

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](https://doi.org/10.17487/RFC9605 "https://doi.org/10.17487/RFC9605")

Pauly, T., Kinnear, E., & Schinazi, D. (2022). *An Unreliable Datagram Extension to QUIC* (Techreport RFC 9221). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC9221 "https://doi.org/10.17487/RFC9221")

Perkins, C., Westerlund, M., & Ott, J. (2021). *Media Transport and Use of RTP in WebRTC* (Techreport RFC 8834). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC8834 "https://doi.org/10.17487/RFC8834")

Rescorla, E. (2021). *WebRTC Security Architecture* (Techreport RFC 8827). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC8827 "https://doi.org/10.17487/RFC8827")

ROS 2 Documentation Contributors. (n.d.). *Quality of Service Settings*. ROS 2. [github.com](https://github.com/ros2/ros2_documentation/blob/jazzy/source/Concepts/Intermediate/About-Quality-of-Service-Settings.rst "https://github.com/ros2/ros2_documentation/blob/jazzy/source/Concepts/Intermediate/About-Quality-of-Service-Settings.rst")

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](https://doi.org/10.17487/RFC3550 "https://doi.org/10.17487/RFC3550")

Shelby, Z., Hartke, K., & Bormann, C. (2014). *The Constrained Application Protocol (CoAP)* (Techreport RFC 7252). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC7252 "https://doi.org/10.17487/RFC7252")

The gRPC Authors. (n.d.a). *Cancellation*. gRPC. [grpc.io](https://grpc.io/docs/guides/cancellation/ "https://grpc.io/docs/guides/cancellation/")

The gRPC Authors. (n.d.b). *Core Concepts, Architecture and Lifecycle*. gRPC. [grpc.io](https://grpc.io/docs/what-is-grpc/core-concepts/ "https://grpc.io/docs/what-is-grpc/core-concepts/")

The gRPC Authors. (n.d.c). *Deadlines*. gRPC. [grpc.io](https://grpc.io/docs/guides/deadlines/ "https://grpc.io/docs/guides/deadlines/")

The gRPC Authors. (n.d.d). *Retry*. gRPC. [grpc.io](https://grpc.io/docs/guides/retry/ "https://grpc.io/docs/guides/retry/")

Thomson, M., & Benfield, C. (2022). *HTTP/2* (Techreport RFC 9113). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC9113 "https://doi.org/10.17487/RFC9113")

Thomson, M., & Turner, S. (2021). *Using TLS to Secure QUIC* (Techreport RFC 9001). Internet Engineering Task Force. [doi.org](https://doi.org/10.17487/RFC9001 "https://doi.org/10.17487/RFC9001")

WebRTC for the Curious Contributors. (n.d.). *WebRTC for the Curious*. [webrtcforthecurious.com](https://webrtcforthecurious.com/ "https://webrtcforthecurious.com/")

WHATWG. (n.d.). *HTML Standard: Server-Sent Events*. WHATWG. [html.spec.whatwg.org](https://html.spec.whatwg.org/multipage/server-sent-events.html "https://html.spec.whatwg.org/multipage/server-sent-events.html")

World Wide Web Consortium. (2026). *WebTransport* (N. Jaju, V. Vasiliev, & J.-I. Bruaroey, Eds.). World Wide Web Consortium. [w3.org](https://www.w3.org/TR/2026/CR-webtransport-20260730/ "https://www.w3.org/TR/2026/CR-webtransport-20260730/")
