RFC 是编号连续的公开文档,谁都能免费下载——这一点比内容更重要。 同一份规范的头部格式,四十年前和今天完全不同,那就是版本的痕迹。
2.2.2 讲的是标准化的思路,这一节讲标准长什么样。 这一节会真拉两份 RFC 对照,一份 1981 年、一份 2022 年。
一、RFC 是什么
三个特征,缺一不可:
| 特征 | 含义 | 为什么重要 |
|---|---|---|
| 编号连续 | 从 1 开始,只增不改号 | 引用永远有效 |
| 全文公开 | 任何人免费下载 | 实现不必求人 |
| 只增不删 | 作废也留着,标 Historic | 历史可追溯 |
第一行那个「只增不改号」是关键设计:
一份 RFC 一旦发布,编号就固定了,内容也不会被原地修改。
要改就发一份新的,然后在新文档里写「Obsoletes: 793」。
所以「RFC 793」永远指 1981 年那份 TCP 规范,
不会某天变成别的内容——这让所有引用都稳定可靠。
第三行是「可追溯」的来源:被废弃的 RFC 不删除,只标 Historic,
所以你能查到「当年为什么这么设计」。
这一点在工程上极有价值——很多「看起来奇怪的规定」,答案就在某份 Historic 文档里。
二、两份对照
同一份规范的头部,四十年前后差别很大:
| 字段 | RFC 791(1981) | RFC 9293(2022) |
|---|---|---|
| 编号 | RFC: 791 |
Request for Comments: 9293 |
| 状态 | 没有这一栏 | Category: Standards Track |
| 替代关系 | 没有 | Obsoletes: 793, 879, ... |
| 作者单位 | prepared for DARPA | W. Eddy, Ed. / MTI Systems |
| 标准化号 | 无 | STD: 7 |
第二、三行是新加的:1981 年那份没有「状态」也没有「替代关系」,
因为当年还没有「成熟度等级」这套制度。
这套制度是后来才建立的,所以老文档里查不到,只能靠外部索引判断。
第四行那个 STD: 7 是另一套编号:STD 系列是「已经是正式标准」的汇总编号,
一个 STD 号可能对应好几份 RFC。
所以「查 RFC 9293 是不是正式标准」的答案在 STD: 7 这一行。
三、怎么读一份 RFC
顺序很重要,能省掉大量时间:
| 顺序 | 看什么 | 能回答什么 | |---|---|---|---| | 1 | 头部 | 是不是现行版、有没有被替代 | | 2 | Status of This Memo | 能不能商用、是不是草案 | | 3 | 目录与 Abstract | 这份文档管不管你要问的事 | | 4 | 搜 MUST/SHOULD | 硬边界在哪 |
第一步最容易跳过,但最重要:很多网上流传的「RFC 编号」其实是废弃版,
照着它实现就会出错。
先看头部有没有 Obsoleted By,一步就能排除。
第四步是效率技巧:一份 RFC 几十页,但硬性要求往往只有十几条,全部标着 MUST。
先搜这三个词,再回头看上下文,比通读一遍快得多。
顺带说一句「Status of This Memo」那一段:它写的是「这份文档的使用许可」,
老 RFC 里有「不得部分引用」这类限制,新的一般是自由使用。
这段话经常被跳过,但它决定了你能不能把内容抄进产品文档。
四、动手 Demo:RFC 的开头是一套固定格式
真拉两份对照:一份 1981 年的老规范,一份 2022 年的新规范。 头部字段的差异,就是标准化制度演进留下的痕迹。
import urllib.request
def head(url, n):
req = urllib.request.Request(url, headers={'User-Agent': 'demo'})
with urllib.request.urlopen(req, timeout=8) as r:
raw = r.read(n)
if raw.startswith(b'\xef\xbb\xbf'):
raw = raw[3:]
return raw.decode('latin-1')
for tag, url, n in (('RFC 791', 'https://www.rfc-editor.org/rfc/rfc791.txt', 900),
('RFC 9293', 'https://www.rfc-editor.org/rfc/rfc9293.txt', 2600)):
print('==', tag)
got = 0
for l in head(url, n).split('\n'):
if not l.strip():
continue
print(l.rstrip()[:78])
got += 1
if got >= 9:
break
实跑输出:
--------------------------------------------------------------------
RFC 的开头是一套固定格式
--------------------------------------------------------------------
**标准文档不是散文,它有固定格式。**下面真拉两份对照:一份 1981 年的老规范,一份 2022 年的新规范。
**RFC 791(1981,IP)**
RFC: 791
INTERNET PROTOCOL
DARPA INTERNET PROGRAM
PROTOCOL SPECIFICATION
September 1981
prepared for
Defense Advanced Research Projects Agency
Information Processing Techniques Office
1400 Wilson Boulevard
**RFC 9293(2022,TCP)**
Internet Engineering Task Force (IETF) W. Eddy, Ed.
STD: 7 MTI Systems
Request for Comments: 9293 August 2022
Obsoletes: 793, 879, 2873, 6093, 6429, 6528,
6691
Updates: 1011, 1122, 5961
Category: Standards Track
ISSN: 2070-1721
Transmission Control Protocol (TCP)
**两份的头部长得完全不一样,这就是版本的痕迹**:
**1981 年那份只有 `RFC:` 编号和标题,没有状态、没有作者单位**;
**2022 年那份有工作组、编号、类别、ISSN、作者、日期一整套。**
**「Stream:」、「Category:」这些字段就是成熟度等级**,**它们决定了「这是正式标准,还是讨论稿」。**
**2.2.4 会讲这套等级怎么晋升。**
RFC 791 的头部只有 RFC: 791、标题、September 1981 和「prepared for DARPA」:
没有状态、没有替代关系、没有作者署名。
RFC 9293 的头部有六行元数据:STD: 7、Request for Comments: 9293、
Obsoletes: 793, 879, ...、Updates: 1011, 1122, 5961、Category: Standards Track、
ISSN: 2070-1721。这六行就是「这份文档在标准体系里的位置」。
注意 RFC 9293 文件开头有一个 BOM:那是 UTF-8 的字节顺序标记,
直接按 latin-1 解码会变成三个乱码字符,所以代码里先判断并去掉它。
读文本文件时遇到「开头三个怪字符」,多半就是这个原因。
30 秒实验
- 把
n调大,找出 RFC 9293 里Obsoletes那一行的完整内容。 - 拉一份 RFC 768,看它的头部有没有
Category这一栏。 - 搜一下你关心的话题对应的 RFC 编号,先看它有没有被
Obsoleted By。
常见误区
- 以为 RFC 就是「标准」。 RFC 里有大量讨论稿、实验稿、甚至笑话, 要看头部的 Category 才知道它是什么。
- 以为 RFC 会被「更新」成新内容。 编号固定、内容不改,要改就发新的并标
Obsoletes。 - 以为老 RFC 没价值。 被废弃的也留着,很多「为什么这么设计」的答案就在 Historic 文档里。
自测三问(点开对答案)
1. RFC 的「只增不改号」带来什么好处? —— **引用永远有效**:RFC 793 永远指 1981 年那份规范,不会某天变成别的内容。 要改就发新的并标 Obsoletes。 2. RFC 791 与 RFC 9293 的头部差在哪? —— **老的那份没有状态、没有替代关系、没有作者署名**; 新的有 Category、Obsoletes、Updates、STD 号等六行元数据。 3. 读一份 RFC 应该先看什么? —— **先看头部有没有被替代**,再看 Status of This Memo,然后看目录, 最后搜 MUST/SHOULD 找硬边界。下一节讲 RFC 是怎么被「晋升」成标准的。
- ☐ (本节完,下一节 2.2.4 TCP/IP的标准化流程)