摘要
- TCP MSS 选项由接收方在带 SYN 的报文里声明,约束的是对方发向自己的 TCP 数据长度;连接两个方向可以有两个不同值,它们不是一次共同议价的结果。
- 发送方不能照抄收到的 MSS。它必须把远端接收上限与 IP 层当前允许的发送尺寸取较小值,并按每个报文实际携带的 IP/TCP 选项缩短数据。
- MSS 既不是路径 MTU,也不是接收窗口、应用消息边界或实际包长。它是一条有方向、有限范围、需要与其他证据合并的上界。
两个 SYN,没有一个共同答案
抓包工具常把握手中的 MSS 展示成一个醒目的数字。观察者很容易说:“这条连接协商成了 1460。”但如果继续看反方向,可能还有 1200。哪一个才是结果?答案是:问题问错了。
RFC 793 在 1981 年把 Maximum Segment Size 定义成选项 Kind 2、长度 4,其中两字节的值表示“发送这个报文的 TCP 所能接收的最大段尺寸”。它只能出现在带 SYN 的连接初始报文中。数字随握手而来,却不是双方共同选择的连接常量。
客户端在 SYN 中写 1460,意思是服务器向客户端发送时不能把 TCP 数据部分做得比 1460 更大。服务器在 SYN-ACK 中写 1200,意思是客户端向服务器发送时受到 1200 的接收上限约束。两个声明分别跨过连接,作用在相反方向。链路可能不对称,缓冲和接口也可能不同,因此两个值不同完全合理。
这也是 RFC 879 在 1983 年特意纠正的语言。它把 MSS 称为 announcement,并指出这个动作经常被误叫成 negotiation。真正的协商通常意味着双方围绕一个共享参数达成共同结果;MSS 没有这样的选择步骤。每一方只对自己能够接收什么负责。
536不是神秘传统,而是减法的遗迹
早期 IPv4 主机必须能接收并重组 576 字节的数据报。在没有更多知识时,发送者也不应假定目的主机能接收更大的数据报。固定 IPv4 头占 20 字节,固定 TCP 头再占 20 字节,于是剩给 TCP 数据的默认空间是 536 字节。
RFC 879 用这个关系澄清了 MSS:它计算的是 TCP 数据字节,不包括 IP 头和 TCP 头。SYN 与 FIN 虽然各占一个序列号位置,却也不是 MSS 所计数的数据字节。这个区分阻止了另一个常见错误——把“段”当成线上整个 IP 包。
后来 IPv6 的最低链路 MTU 是 1280,固定 IPv6 头 40 字节、TCP 固定头 20 字节。因此当前 RFC 9293 在没有收到 MSS 选项时规定,IPv4 的默认发送 MSS 为 536,IPv6 为 1220。缺少选项并不意味着“无限”或“按本地接口随便发”;协议提供的是保守默认值。
这些数字记录了共同最低能力,而不是今天某条路径的典型性能。把 536 看成古老低速网络的配置建议,或把 1220 看成所有 IPv6 连接的目标段长,都扩大了它们的含义。它们只在对方没有声明更明确的接收上限时填补证据空白。
收到的上限还不是要发送的尺寸
RFC 1122 把主机责任写得更明确:TCP 必须支持发送和接收 MSS 选项;没有收到时采用默认值;真正发出的最大段,即 effective send MSS,必须同时服从远端的发送上限与 IP 层允许的最大传输尺寸。
这一步把两类证据分开。远端 MSS 反映对方能够接收和重组的上界。IP 层的 MMS_S 或有效 MTU 反映本端沿当前上下文能够交给网络的上界。远端即使愿意收 9000 字节,也不能让中间路径自动承载 9000 字节。路径即使能承载大包,也不能授权发送者超过对方声明的接收能力。
所以实际计算不是“采用对方的 MSS”,而是先取较小的约束,再扣除当前头部。发送者还可能因为拥塞窗口、接收窗口、待发送数据不足、重传边界、调度或本地策略而发送更短的段。一个实际载荷小于 MSS 的包,不能单独证明存在中间设备改写,也不能证明路径只能走这么小。
MSS 与 Path MTU 的区别尤其重要。已发布的 Path MTU Discovery 历史研究的是发送者如何从路由器错误和端到端探测中更新路径尺寸。MSS 则是另一端主机对接收能力作出的方向性声明。两者会在发送方计算中相遇,却不是同一事实,也不能互相代替。
为什么不能预先替未来选项留空
头部长度会变化。TCP 时间戳、认证或其他选项可能出现在某些数据段上,IP 选项或扩展头也可能改变每个包的开销。早期文字由此引发争论:发出 MSS 时,是否应该先把可能出现的所有选项长度扣掉?
RFC 6691 给出的短答案很严格:计算要写入 MSS 选项的值时,只减固定 IP 和 TCP 头;不要为可能出现的可变选项预扣空间。真正发送某个包时,发送者必须按那个包实际携带的选项长度减少 TCP 数据。
理由不是追求乐观,而是把判断放在唯一知道事实的一方。接收者在握手时不知道发送者以后每个包会组合哪些选项;一个固定 MSS 也不可能准确表达所有组合。如果接收者预扣一次,发送者又在逐包计算时再扣一次,数据段会无谓变小。如果两边都不扣,带选项的包又可能过长、被分片或丢弃。
RFC 6691 还纠正了 RFC 879 中把 IP Security 选项直接从通告 MSS 扣除的旧例。RFC 879 的勘误修正过那个例子的填充算术,但更晚的规范指出,问题不只差一个字节,而是扣减职责放错了位置。当前规则以 RFC 9293 的汇总文本为准:通告用固定头,发送按实际头逐包调整。
小得过头也会丢失能力
保守并非没有代价。RFC 6691 明确提醒,MSS 报得太小,会限制 Path MTU Discovery 利用更大路径的能力。路径可能允许更大包,发送者也可能拥有足够拥塞与窗口空间,却仍受对方报出的较小接收上限约束。
这不是鼓励夸大接收能力。对于有效 MTU 会变化的接口,例如头部压缩偶尔需要恢复完整头的场景,规范建议按最小有效 MTU 计算通告。原因在于重传可能恰好发生在需要更大头部的时候。一个只在最佳压缩状态下成立的上限,并不是可重复执行的接收承诺。
IPv6 jumbogram 又暴露了 16 位字段的边界。RFC 6691 规定,为支持超过 64K 的 TCP 段,MSS 值 65535 被当作“无穷”,实际大小再由 Path MTU Discovery 决定。这不是说路径无限大,而是承认一个旧字段无法完整携带新范围,必须把最终测量交回别的机制。
注册表保存语法,不保存一次连接的事实
IANA TCP 参数注册表 仍把 Kind 2、长度 4列为 Maximum Segment Size,并指向 RFC 9293。这证明共享语法和引用链仍被维护。它不证明任何操作系统发出了什么值,也不证明中间设备是否改写,更不能证明路径能够承载该值。
RFC 9293 在 2022 年废止并汇总了 RFC 793、879、6691 等旧文档的 TCP 规则。历史价值不在于一个数字几十年不变,而在于责任边界逐步变清:接收者通告自己的上限;发送者结合远端声明与 IP 约束;每个包的可变开销由真正构造它的一方承担。
一个 MSS 因此只是一条有出处的上界。要理解连接,至少要保存两个方向的原始声明、缺省规则、发送方的有效计算和实际包。把它们压成“协商 MSS”,会让最方便的单个字段获得它从未拥有的权力。
来源与证据边界
- RFC 793 — Transmission Control Protocol
- RFC 879 — The TCP Maximum Segment Size and Related Topics
- RFC 1122 — Requirements for Internet Hosts — Communication Layers
- RFC 6691 — TCP Options and Maximum Segment Size
- RFC 9293 — Transmission Control Protocol (TCP)
- IANA — Transmission Control Protocol (TCP) Parameters
这些来源定义规范、修订关系与注册状态,不提供当前部署比例、系统默认值、中间设备行为或某次真实连接的路径测量。本文不把注册、建议或公式当成现场观测。
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
