本文核心结论: 网络延迟优化不是单一手段能解决的,而是贯穿客户端渲染、网络传输与服务端模拟的全链路系统工程。正确路线是:先量化延迟、抖动、丢包三项指标,再定位瓶颈,最后在客户端预测补偿、服务端延迟补偿与协议选型三个层面逐一击破。本文给出可直接运行的测量工具与算法示例,覆盖 TCP/UDP/QUIC 全协议栈,面向游戏开发者与网络工程师。
一、延迟为何是游戏体验的第一变量
对竞技类游戏而言,网络延迟(Latency)是体验的第一杀手。一次 50ms 的额外往返,意味着你的开火指令比对手晚 3 帧到达服务器(以 60Hz 渲染计算),足以决定一次对枪的胜负。然而,玩家感知到的”卡顿”往往不是单一指标造成的,而是延迟(Latency)、抖动(Jitter)、丢包(Packet Loss) 三者叠加的结果。游戏网络延迟优化,首先要建立对这三个指标的清晰认知。
1.1 延迟:从输入到画面的完整链路
延迟的权威定义是数据包往返时间 RTT(Round-Trip Time)。对玩家而言,更贴近感知的是”输入到显示”总延迟(Input-to-Display Latency),它由四段构成:
输入采样延迟 + 客户端本地处理 + 网络
其中网络 RTT 通常只占总延迟的一部分。一个常见的误区是:玩家以为”延迟高”纯粹是网络问题,实际上客户端渲染排队(帧时间预算超支)、服务器 tick 间隔都可能贡献更多。因此优化第一步永远是测量分解,详见第三章。
1.2 抖动:比延迟更隐蔽的体验杀手
抖动(Jitter)指 RTT 的波动幅度。两条链路的平均延迟都是 60ms,一条稳定在 58–62ms,另一条在 20–100ms 之间波动——后者的游戏体验会明显更差:角色位置”漂移”、命中判定时灵时不灵。RFC 3550 将抖动定义为传输时间差的平滑绝对值,是网络质量监控的标准指标。
1.3 丢包:补偿算法的噩梦
丢包(Packet Loss)对游戏的影响与协议强相关:UDP 下包丢了就丢了,表现为瞬移、技能丢失;TCP 下丢包会触发拥塞窗口减半与重传,表现为周期性卡顿(队头阻塞)。即使在 2% 的丢包率下,30Hz 的更新频率意味着每秒约 0.6 个包丢失,对射击判定的影响是灾难性的。
| 指标 | 优秀 | 可接受 | 较差 | 玩家感知 |
|---|---|---|---|---|
| 延迟 RTT | < 50ms | < 100ms | > 150ms | 输入反馈迟滞、对枪吃亏 |
| 抖动 Jitter | < 10ms | < 25ms | > 40ms | 角色漂移、位置回弹 |
| 丢包率 | < 0.5% | < 2% | > 5% | 瞬移、技能丢失、命中失效 |
数据说明:以上阈值为行业通行经验值(综合 Valve、Epic 公开技术文档与社区共识,2024 年汇总),具体游戏类型可上下浮动——FPS 比 MMO 严苛得多。
二、延迟从哪来:物理定律与协议开销
要优化延迟,必须先知道延迟从哪里来。一条数据包从玩家主机到游戏服务器,累计的延迟由以下成分构成。
2.1 物理传播延迟:不可压缩的部分
光在光纤中的传播速度约为 2×10⁸ m/s(约为真空光速的 2/3)。北京到上海直线距离约 1000km,单程约 5ms,RTT 约 10ms;跨太平洋(约 12000km)单程约 60ms,RTT 超过 120ms。这部分延迟由物理定律决定,代码无法消除,唯一的手段是让服务器离玩家更近——边缘节点与 Anycast 部署(见 5.1 节)。
2.2 串行化延迟:带宽的隐性成本
一个 1500 字节的 MTU 数据包逐比特发送到链路所需时间与带宽成反比:10Mbps 链路约 1.2ms,100Mbps 约 0.12ms。高带宽不等于低延迟——在 10Mbps 的共享链路上,即使排队为零,串行化本身就是 1ms 级的固定开销。
2.3 排队延迟与缓冲区膨胀(Bufferbloat)
路由器收到超出出端口速率的流量时,数据包进入缓冲区排队。现代家用路由器普遍配置大缓冲区(为吸收突发流量),但当拥塞持续时,排队延迟可达数百毫秒——这就是著名的 Bufferbloat 问题。对游戏这种低带宽、高实时性流量,Bufferbloat 往往比物理距离影响更大。
2.4 协议与系统开销:隐藏的延迟杀手
TCP 三次握手:建立连接即消耗 1 个 RTT;
TLS 握手:TLS 1.2 需要额外 1–2 个 RTT,TLS 1.3/QUIC 0-RTT 可消除;
Nagle 算法 × 延迟 ACK:Nagle 等待合并小包,延迟 ACK 等待合并确认,两者交互可能额外引入约 40ms 延迟——游戏服务器务必开启
TCP_NODELAY(UDP 无此问题);TCP 队头阻塞(Head-of-Line Blocking):一个包丢失会阻塞其后所有已到达的数据,100ms RTT 链路上一次丢包恢复即约 100ms 的卡顿;
慢启动与拥塞窗口:新建连接初期 cwnd 小,吞吐受限,延迟敏感流量开局不利。
2.5 处理延迟:客户端与服务端侧
除网络外,两端自身也有处理开销:客户端渲染队列饱和、垂直同步(VSync)引入的帧等待、服务器物理引擎步长、GC 暂停、数据库查询等。这些”看不见的延迟”常常被错误地归咎于网络。
三、先测量再动手:延迟的检测与量化
“没有测量就没有优化”是网络工程的第一原则。游戏网络延迟优化的落地,从一套可信的测量工具开始。
3.1 时钟同步与单向延迟
RTT 用同一台主机的时钟即可精确测量;但要拆解单向延迟(玩家→服务器、服务器→玩家),必须解决时钟同步问题:NTP 精度在毫秒级,PTP(IEEE 1588)可到亚微秒级。对绝大多数游戏场景,测量 RTT 并把链路拆成”上行/下行/服务器处理”三个分段(通过服务器打时间戳实现)已足够定位问题。
3.2 代码示例一:UDP 回声延迟测量工具
下面这套工具用 UDP 回声模拟真实游戏流量(区别于 ICMP ping——部分运营商会对 ICMP 做限速或丢弃,导致测量失真),同时输出 RTT、抖动与丢包率。它由服务端与客户端两个脚本组成,可直接在本机或内网运行。
服务端 udp_echo_server.py:
import socket import def main() -> None: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(("0.0.0.0", 7777)) print("[Server] 监听 UDP 0.0.0.0:7777 ...") while True: data, addr = sock.recvfrom(2048) # 客户端包格式: 2 字节序列号 + 8 字节纳秒时间戳(共 10 字节) if len(data) == 10: sock.sendto(data, addr) # 原样回显,客户端用自身时钟计算 RTT sock.sendto(data, if __name__ == "__main__": if __ main()
客户端 udp_latency_probe.py:
"""UDP 延迟 用法: python udp_latency_probe.py <服务器IP> [端口=7777] [包数=20] """ import socket import struct import sys import time import time def measure(host: str, port: int = 7777, count: int = 20) -> None: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(1.0) sock.sett rtts: list[float] = [] lost = 0 jitter_ns = 0.0 # 抖动估计(纳秒) prev_transit = 0.0 # 上一包的传输时间(纳秒) prev_transit = 0.0 for seq in range(count): ts = time.time_ns() sock.sendto(struct.pack("!HQ", seq, ts), (host, port)) try: echo, _ = sock.recvfrom(2048) arrival = time.time_ns() transit = arrival - ts # 传输时间 = RTT rtts.append(transit / 1e6) if seq > 0: # RFC 3550: J += (|D|-J)/16 d = transit - prev_transit jitter_ns += (abs(d) - jitter_ns) / 16 prev_transit = transit except socket.timeout: lost += 1 time.sleep(0.1) time.sleep(0.1 sock.close() if not rtts: print("[Client] 全部超时:请检查服务器进程与防火墙是否放行 UDP 7777") return print(f"成功={len(rtts)} 丢包={lost} 丢包率={lost / count * 100:.1f}%") print(f"RTT min={min(rtts):.2f} ms avg={sum(rtts)/len(rtts):.2f} ms max={max(rtts):.2f} ms") print(f"抖动 Jitter={jitter_ns / 1e6:.2f} ms") print(f"抖动 Jitter if __name__ == "__main__": host = sys.argv[1] if len(sys.argv) > 1 else "127.0.0.1" host = sys.argv[1] measure(host)
运行方法:先在服务器执行 python udp_echo_server.py,再在客户端执行 python udp_latency_probe.py <IP>。抖动计算采用 RFC 3550 的指数平滑公式,比简单标准差更贴近流媒体/游戏实时传输的感知。
3.3 代码示例二:ping 快速链路健康检查脚本
生产环境里,运营同学需要一个”一眼看出链路好坏”的快速脚本。下面的脚本包装系统 ping,输出 RTT 分位数与丢包率,Windows/Linux/macOS 通用:
"""game_ping_check.py —— 快速链路健康 Windows / Linux / macOS 通用,兼容中文与英文 ping 输出。 """ import re import statistics import subprocess import sys import sys def quick_check(host: str, count: int = 30) -> None: flag = "-n" if sys.platform == "win32" else "-c" raw = subprocess.run(["ping", flag, str(count), host], capture_output=True).stdout # 中文 Windows 的 ping 输出为 GBK 编码,做兼容解码 try: out = raw.decode("utf-8") except UnicodeDecodeError: out = raw.decode("gbk", errors="ignore") out = raw.decode(" # 兼容中文("时间=1ms")与英文("time<1ms")两种时间戳格式 rtts = [float(v) for v in re.findall( r"(?:时间|time)\s*[=<]\s*(\d+(?:\.\d+)?)\s*ms", out, re.I)] if not rtts: print("未解析到 RTT 数据,请检查主机名或网络连通性。") return # 兼容中文"0% 丢失"与英文"0% packet loss"两种丢包表述 m = re.search(r"(\d+)%\s*(?:丢失|loss|packet\s*loss)", out, re.I) loss = int(m.group(1)) if m else -1 p95 = sorted(rtts)[max(0, int(len(rtts) * 0.95) - 1)] print(f"样本={len(rtts)} p50={statistics.median(rtts):.1f} ms " f"p95={p95:.1f} ms max={max(rtts):.1f} ms 丢包率={loss}%") f if __name__ == "__main__": quick_check(sys.argv[1] if len(sys.argv) > 1 else "1.1.1.1") quick_check(sys.argv[1
注意:ICMP ping 可能被运营商限速或屏蔽,测量结果仅作参考;正式评估以 3.2 节的 UDP 回声结果为准。
3.4 端到端链路分解与遥测
生产环境的正确做法是在游戏协议内埋点:每个上行包携带客户端发送时间戳,服务器记录接收时间并回填处理时长,客户端即可把总延迟分解为:上行分段、服务器处理时间、下行分段。配合灰度监控(p50/p95/p99 分位数看板),可以第一时间发现某地区玩家的网络劣化——这是游戏网络延迟优化的数据底座。
四、客户端侧优化:把延迟藏到玩家感知之外
客户端优化的核心思想是:用本地计算换取网络时间。即使网络延迟无法消除,也要让玩家的操作反馈看起来是即时的。
4.1 输入与渲染管线优化
外设采样频率:1000Hz 游戏鼠标与 125Hz 普通鼠标在帧内采样时间上差距可达数毫秒;
关闭 VSync 或改用无撕裂模式(如可变刷新率),避免渲染队列引入 1–2 帧等待;
压缩”输入→渲染”流水线中的帧缓冲层级(如 Reflex 类低延迟技术);
固定时间步长(Fixed Timestep)配合插值,避免物理模拟随帧率抖动。
4.2 客户端预测性补偿(Client-Side Prediction)
预测性补偿是 FPS/竞速类游戏的基石技术:客户端收到输入后立即本地模拟,不等待服务器确认;服务器随后返回权威状态,若与本地预测偏差超过阈值,客户端回滚到权威状态并重放(Replay)该时刻之后的输入。玩家看到的是”即时响应 + 偶发小修正”,而非”按下按键 100ms 后才有反应”。
4.3 代码示例三:预测性补偿与回滚重放
"""client_pred 运行: python client_prediction.py """ DT = 0.05 # 本地模拟步长(50ms) EPSILON = 0.01 # 允许偏差(米),超过则触发回滚 EPSILON = 0. class Prediction: def __init__(self) -> None: self.x = 0.0 # 本地预测位置 self.v = 0.0 # 当前速度 self.seq = 0 self.inputs: dict[int, tuple[float, float]] = {} # seq -> (速度, 预测后位置) self def apply_input(self, v: float) -> int: """玩家输入到达:立即本地模拟,获得零延迟手感。""" self.seq += 1 self.x += v * DT self.inputs[self.seq] = (v, self.x) return self.seq return self.se def on_server_state(self, acked_seq: int, server_x: float, server_v: float) -> bool: """服务器权威状态回包:偏差超阈值则回滚重放,否则保持本地预测。""" _, predicted_x = self.inputs.get(acked_seq, (0.0, self.x)) if abs(predicted_x - server_x) <= EPSILON: # 预测与权威一致(误差范围内):保持本地预测,无需回滚。 # 注意:不能把当前状态覆盖为 acked 时刻的旧状态,否则会丢掉后续预测。 return False # ---- 回滚:以权威位置为基准,重放该 seq 之后的全部输入 ---- self.x, self.v = server_x, server_v for s in sorted(self.inputs): if s > acked_seq: v, _ = self.inputs[s] self.x += v * DT self.inputs[s] = (v, self.x) # 同步修正历史,避免后续误判 return True def cleanup(self, acked_seq: int) -> None: for s in [k for k in self.inputs if k <= acked_seq]: del self.inputs[s] del self.input def demo() -> None: p = Prediction() inputs = [2.0, 2.0, 0.0, 3.0, 3.0, 0.0] # 玩家连续 6 步的速度输入 LATENCY_STEPS = 3 # 模拟 150ms 网络延迟 s_x = 0.0 for step, v in enumerate(inputs, start=1): p.apply_input(v) if step > LATENCY_STEPS: # 服务器此刻才处理"三步前"的输入 idx = step - LATENCY_STEPS sv = inputs[idx - 1] if step == 5: # 服务器权威修正:第5步"撞墙",速度归零 sv = 0.0 s_x += sv * DT p.on_server_state(idx, s_x, sv) # 回包并触发可能的回滚 p.cleanup(idx) print(f"step={step:2d} | 本地预测 x={p.x:6.3f} | 服务器权威 x={s_x:6.3f}") print(f"step={step if __name__ == "__main__": demo() demo
运行输出中可以看到:本地预测始终领先服务器 3 步(模拟网络延迟),且对同一输入序号的判定在前 4 步完全一致、无回滚;第 5 步服务器因”撞墙”给出权威修正,客户端本地位置从 0.500 回滚重放到 0.400,随后双方重新对齐——这正是真实游戏中玩家”没感觉到延迟,只在撞墙时有一帧修正”的机制。生产实现还需叠加:服务器延迟补偿(见 5.3 节)、插值缓冲(见 4.4 节)与快照压缩。
4.4 插值(Interpolation)与外推(Extrapolation)
对其他实体(队友、敌人),客户端在收到两个权威状态之间用插值平滑过渡,缓冲时长通常取 2 倍平均 RTT;当状态到达不及时时,则用上一帧速度外推预测。插值缓冲与延迟是此消彼长的关系——缓冲越大越平滑,但”看起来”越滞后,这也是抖动会直接导致角色漂移的原因。
五、服务端侧的优化手段
5.1 边缘节点与 Anycast 部署
物理传播延迟只能靠地理位置解决:在全球主要城市群部署边缘节点,通过 Anycast 让玩家自动接入最近的节点;国内游戏可选用多线 BGP 机房,减少跨运营商(电信/联通/移动)的绕行。这是”降延迟”最立竿见影的运营手段。
5.2 Tick Rate:服务器模拟频率的权衡
服务器每秒的模拟次数(Tick Rate)直接决定服务器侧延迟下限:64Hz 的 tick 意味着玩家指令最多要等约 15.6ms 才被处理,128Hz 则缩短到约 7.8ms(CS:GO 竞技服 128 tick 即为此)。但更高的 tick 会线性放大 CPU 与带宽成本,且对高丢包网络的收益递减,需按游戏类型权衡。
5.3 服务器延迟补偿(Lag Compensation)
射击判定的经典难题:玩家 A 的屏幕上,B 在 100ms 前的位置已经被命中,但服务器在收到 A 的开火包时,B 已经移动。Valve 的经典方案是:命中判定时,把 A 的视角回溯到其客户端所见的历史时间点(基于 A 的 RTT),在历史世界状态中计算射线。这样”所见即所中”,但也会引入”从掩体后被击杀”的观感问题——补偿窗口需要按游戏类型仔细调参。
5.4 代码示例四:BBR 风格的带宽估算与发送速率控制
游戏服务器需要知道当前可用带宽,以决定快照发送速率。Google BBR 的核心洞察是:用”投递速率”(delivery rate)而非”发送速率”度量网络容量。下面是一个简化实现:
"""bandwidth_estimator 运行: python bandwidth_estimator.py """ import time import time SAMPLE_WINDOW = 0.2 # 采样窗口(秒) MAX_SAMPLES = 10 # max filter 保留的窗口数(对应 BBR 的 ~10 RTT) GAIN = 1.25 # pacing gain:以 1.25x 探测,避免自限流 GAIN = 1. class BandwidthEstimator: def __init__(self) -> None: self.window_bytes = 0.0 self.window_start = time.monotonic() self.samples: list[float] = [] self.pacing_rate = 0.0 self.pacing_rate def on_ack(self, acked_bytes: float, now: float | None = None) -> float: """每个 ACK/确认包到达时调用;acked_bytes 为该包确认的字节数。""" now = now if now is not None else time.monotonic() self.window_bytes += acked_bytes if now - self.window_start < SAMPLE_WINDOW: return self.pacing_rate rate = self.window_bytes / (now - self.window_start) # 投递速率 self.samples.append(rate) if len(self.samples) > MAX_SAMPLES: self.samples.pop(0) btl_bw = max(self.samples) # max filter self.pacing_rate = btl_bw * GAIN # 发送速率 self.window_bytes, self.window_start = 0.0, now return self.pacing_rate return self.pacing_rate def demo() -> None: est = BandwidthEstimator() est.window_start = 0.0 # 演示模式:使用模拟时钟 true_bw = 20e6 / 8 # 真实瓶颈 20Mbps -> 2.5MB/s t, step = 0.0, 0.01 while t < 8.0: # 模拟 8 秒,链路利用率 90% est.on_ack(true_bw * step * 0.9, now=t) t += step print(f"真实瓶颈: {true_bw * 8 / 1e6:.1f} Mbps") print(f"估算带宽: {est.pacing_rate * 8 / 1e6:.1f} Mbps(含 1.25x 增益)") print(f"估算 if __name__ == "__main__": if demo()
实际系统中,估算出的 pacing_rate 会作为快照/状态同步包的发送速率上限,并与丢包率联动(丢包升高时主动降速并缩短补偿窗口)。这是从”盲目全速发送”走向”感知网络容量”的关键一步。
六、协议怎么选:TCP、UDP 与 QUIC 对比
协议选型决定了延迟与可靠性的基础权衡。Glenn Fiedler 的经典论述指出:实时游戏数据流(位置、输入、命中)应当使用 UDP;需要可靠、按序、有安全语义的数据(登录、聊天、匹配)才值得使用 TCP。
| 特性 | UDP | TCP | QUIC |
|---|---|---|---|
| 建立连接 | 无(0 RTT) | 三次握手(1 RTT) | 0–1 RTT(首次 1-RTT,复用 0-RTT) |
| 可靠性 | 不保证 | 可靠、按序、重传 | 可靠、按序(单流内) |
| 队头阻塞 | 无 | 有(连接级) | 无(多路复用,每流独立) |
| 拥塞控制 | 无(需自实现) | 内置(CUBIC 等) | 内置且可插拔(CUBIC/BBR) |
| 加密 | 无 | TLS(额外握手) | 内置 TLS 1.3 |
| NAT 穿透/连接迁移 | 需自实现 | 差 | 内置(连接 ID 迁移) |
| 适用场景 | 实时位置/输入/命中 | 登录、下载、聊天 | 登录/下载+实时混合、弱网环境 |
6.1 UDP:实时游戏的事实标准
几乎所有 AAA 竞技游戏的核心同步都跑在 UDP 上:无握手、无重传、无队头阻塞,丢包时”宁可丢一个旧包,不阻塞后续新包”。代价是必须在应用层自建可靠性(可靠 UDP 层):对关键事件(开火、掉落)用 ACK + 重传,对高频状态(位置)用”最新覆盖最旧”的新包优先策略。
6.2 TCP:可靠但昂贵
TCP 的可靠性建立在重传与队头阻塞之上:一次丢包会让其后已到达的数据全部等待。此外 Nagle 算法与延迟 ACK 的交互、握手与 TLS 开销,都使其不适合低延迟实时通道。若业务必须用 TCP(如弱网保底通道),务必设置 TCP_NODELAY 并评估减少包数量。
6.3 QUIC:新一代低延迟选项
QUIC(RFC 9000)基于 UDP 实现类 TCP 的可靠性与拥塞控制:0-RTT 建连、多路复用无队头阻塞、可插拔拥塞控制(可上 BBR)、内置加密与连接迁移(换网不重连)。它适合游戏的登录/匹配/下载通道,以及对公网弱网、NAT 穿透有需求的场景;对要求极限低延迟的核心战斗通道,UDP + 自研可靠层的控制力仍然更强。混合架构(QUIC 做带外与元数据通道、UDP 做战斗通道)是当前主流实践。
6.4 面向丢包的增强技术
前向纠错(FEC):冗余编码让接收端无需重传即可恢复少量丢包,适合 1–5% 丢包率的弱网;
新包优先(Most Recent Wins):位置快照类数据不重传旧包;
快照压缩与增量编码:位打包、浮点量化、仅发送变化字段,降低串行化延迟。
七、可直接执行的优化清单
- □
测量基线:用 UDP 回声工具(3.2 节)对目标区域玩家采集 RTT/Jitter/丢包的 p50/p95 分位数;
- □
拆解链路:确认瓶颈在客户端渲染、上行、服务器处理还是下行;
- □
客户端:预测性补偿 + 插值缓冲 + 固定步长,关闭 VSync 队列;
- □
服务端:边缘节点就近接入、合理 tick、服务器延迟补偿调参;
- □
协议:战斗通道 UDP(自研可靠层),登录/下载走 QUIC/TLS;
- □
弱网对抗:FEC、新包优先、动态降级画质与同步频率;
- □
持续监控:把延迟/抖动/丢包接入灰度看板,按地区告警。
常见问答
Q1:游戏延迟高,一定是网络问题吗?
不一定。先用 3.2 节工具测量 RTT:若本机到服务器的 RTT 很低但游戏内仍卡,瓶颈大概率在客户端渲染或服务器 tick 处理。
Q2:为什么换了更贵的加速器,抖动还是大?
加速器解决的是路由绕行与跨运营商问题,无法消除最后一公里(玩家 Wi-Fi、家庭链路)的抖动与丢包。抖动主要来自排队与无线介质,需要从链路质量与协议(FEC、缓冲)两端下手。
Q3:延迟和抖动,哪个对 FPS 影响更大?
高延迟是”稳定的慢”,玩家可以适应;高抖动是”不稳定的时快时慢”,会直接破坏瞄准与命中判定。同等幅度下,抖动对射击类游戏的负面影响通常更明显。
Q4:QUIC 能完全替代 UDP 自研可靠层吗?
不能直接替代。QUIC 的可靠性与拥塞控制适合流式与请求-响应语义,但战斗通道需要的是”最新状态优先”的乱序语义、极致的包格式控制与自定义时钟——这些 UDP 原始套接字仍然最灵活。
小结
游戏网络延迟优化是一道”测量 → 定位 → 分层优化”的系统工程题:物理传播延迟靠边缘节点解决,协议开销靠 UDP/QUIC 选型解决,客户端感知延迟靠预测性补偿与插值解决,服务器判定延迟靠 tick 与延迟补偿解决。优化的目标不是把 RTT 压到零——那不可能——而是在给定链路上,让玩家的感知延迟趋近于零,并让网络劣化表现为可容忍的、可预测的体验。建议从本文的测量工具起步,先建立基线数据,再按清单逐项落地,你会看到竞技体验的质的提升。
延伸阅读
RFC 3550 – RTP: A Transport Protocol for Real-Time Applications(抖动定义):https://datatracker.ietf.org/doc/html/rfc3550
Valve Developer Wiki – Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization:https://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization
Bufferbloat 项目主页(延迟成因与解决思路):https://www.bufferbloat.net/
Cardwell et al., BBR: Congestion-Based Congestion Control, ACM Queue 2016:https://queue.acm.org/detail.cfm?id=3022184
Glenn Fiedler – UDP vs. TCP for Game Networking:https://gafferongames.com/post/udp_vs_tcp/
RFC 9000 – QUIC: A UDP-Based Multiplexed and Secure Transport:https://datatracker.ietf.org/doc/html/rfc9000