IT 论文精读 · PAPER 65
Vinton G. Cerf & Robert E. Kahn · IEEE Transactions on Communications · 1974 年 5 月
1974 年,Vint Cerf 和 Bob Kahn 写了一篇论文,回答一个当时谁都答不好的问题:几张互不相通的网络,怎么才能拼成一张网?他们给出的办法后来有了个你一定听过的名字:TCP/IP。今天你手机发的每条消息、打开的每个网页,走的还是这篇论文定的规矩。互联网之所以叫「互联」网,源头就在这里。
1970 年代初,能用的网络已经不止一张:军方研究用的 ARPANET、用无线电收发的分组无线网、跨大西洋的卫星网……每一张在自己内部都跑得挺好,但彼此之间一个字也传不过去。
像铁路:几个国家各修各的,轨距、票制、信号规则都不一样,火车开到边境就只能停下。网络之间差得更远:一个包能装多大不一样,丢了包管不管不一样,连门牌号写法都各是一套。
最自然的想法是「统一标准」,可这条路走不通——每张网都有自己的主人和设备,谁也没权力让别人推倒重来。
Cerf 与 Kahn 的点子正好反过来:谁都不用改。只在两张网的交界处放一个「中转站」(他们叫它网关),再规定一种大家都认的「内层信封」。
要寄的东西先装进这个内层信封,上面写着全网通用的地址;进了哪张网,这张网就按自己的规矩在外面再套一个本地信封。到了边界,网关拆掉本地信封、按下一张网的规矩换个新的——内层信封从头到尾没被打开过。每张网照旧说自己的方言,边界上有人翻译就行。
这里还有个更反直觉的决定:中间的网络和网关,一律不负责把东西送到。它们只「尽力而为」:能送就送,忙不过来就丢,顺序乱了也不管,网关甚至不记得任何一次通信进行到哪儿——只瞄一眼地址就往下扔。责任全压在两头。
做法像寄一摞明信片:发信人给每张编号;收信人回一句「我到第几号为止都齐了」;发信人超时没等到这句回音,就把没被确认的重寄一遍。收信人还会捎上「我最多还能放下 N 张,别寄太快」——这就是限速。
为什么这么设计?中间不记事,网关就能做得简单又快,坏掉一个换一个也不影响进行中的通信;而「东西齐没齐」,本来也只有收发两头最清楚。
这张「网络的网络」从此能无限往外长:新造一张网不必征得谁同意、不必改动任何既有设备,边上接个网关、认那个内层信封就行。今天的 Wi-Fi、4G、光纤、卫星宽带全是后来才有的网络,却都能直接插进 1974 年画好的这张图。
诚实说一句代价:这套设计把信任全交给两端,论文里没有任何防冒名顶替、防偷看的机制——今天大量安全麻烦的根子,就在「当年那批人彼此都认识、没想过防谁」。
别妄想统一所有网络,而是在边界放网关做翻译、给数据套一个谁都认的内层信封;中间只尽力而为、不记账,靠两端编号 + 确认 + 重发把「可靠」补齐——于是任何一张新网都能随时接进来。这就是互联网。
想看网关与封装的结构图、地址格式和它留下的那些坑? → 切到精读版
用网关(gateway)把彼此不兼容的分组网络在边界处连起来,并定义一种所有网络都认的统一内网包格式与全局地址;中间的网络与网关只做「尽力而为」的转发、不保存任何会话状态,而把可靠性(序号、确认、超时重传、窗口限速)整体推给两端主机上的 TCP。这套「网关 + 封装 + 端到端可靠」的设计就是 TCP/IP 的源头,也是今天整个互联网的骨架。
作者是 Vinton G. Cerf(时在斯坦福)与 Robert E. Kahn(时在 ARPA),论文登在 IEEE Transactions on Communications 1974 年 5 月号。它上承 ARPANET(1969)与 Louis Pouzin 的 CYCLADES——后者的纯数据报思想直接塑造了这里「网络不保证送达」的选择;下启 RFC 675(1974 年底第一份 TCP 规范)、1978 年 TCP 与 IP 拆成两层、1983 年 1 月 ARPANET 整体切换到 TCP/IP。两人以此获 2004 年图灵奖。
1974 年的处境是:分组交换本身已经被证明可行——ARPANET 跑了五年,分组无线网、卫星网也各自建起来了。难题从「一张网怎么建」变成了「几张网怎么互通」。
而这些网彼此的差异是结构性的,不是调个参数就能抹平的:
当时看得见的两条路都不通。统一改造(所有网络换同一套协议)政治上不可能——每张网都有自己的主人、经费与既有设备;逐对定制翻译(给每一对网络写一个转换器)则要 n² 量级的转换器,且每接入一张新网都得回头改所有人。
这篇论文要找的是第三条路:既不要求任何一张网改变自己,又不必为每一对网络定制。Kahn 为此立了几条底线(后来叫「开放架构网络」原则):每张网内部不许被改动;网络之间按尽力而为通信;用一个黑盒子(网关)把它们连起来;整个系统不设全局控制。
在两张网的交界处放一台设备,论文叫它 gateway(网关)。它的形态很特别:网关由两半构成,每一半分别属于它所连的一张网——对网络 1 而言它就是网络 1 里一台普通主机、说网络 1 的方言,对网络 2 亦然;两半在设备内部对接。
为什么这么设计?因为这样一来,两张网谁都不必知道对方存在,也不必为「接入互联网」改一行自己的代码——它只是多了个本地邻居。改动被压缩到边界那一个点上。
光有翻译还不够,还得有一样东西是所有网络共同认的。论文规定了一种统一的「内网包(internetwork packet)」格式:自带包头,里面是全局地址、序号、字节数、标志位与校验和,后面跟着真正要传的数据。
这个包不在任何一张网里裸奔,而是被嵌进当前这张网自己的本地包格式里——像一封信被装进本地邮局的信封。走到边界,网关剥掉旧信封、按下一张网的规矩换上新的,内层那封信一个字不动。这个动作今天叫封装(encapsulation),是分层网络最根本的机制。
地址是关键的一步。论文把全局地址设计成两段式:「网络号 + 该网内的 TCP 标识」——先说「哪一张网」,再说「那张网里的谁」。网关只看网络号就知道往哪转,不必认识全世界每一台主机。这是分层寻址的雏形:今天 IP 的「网络前缀 + 主机部分」与路由器按前缀转发,都是它的直系后代。(论文给网络号只留了 8 位——整个互联网最多 256 张网,这个数字后来成了最常被拿来开玩笑的部分。)
接下来是这篇论文最有影响力、也最反直觉的决定。既然各网的可靠性保证参差不齐,互联网就干脆一条都不要求:中间的网络与网关只负责尽力而为地转发——可以丢包、可以乱序、可以重复,而且网关不为任何一次通信保存状态,它只看一眼地址就转发出去。
那可靠性从哪儿来?全部由两端主机上的 TCP 补齐(注意 1974 年的 TCP 是 Transmission Control Program,一个程序,后来才被拆成协议)。四件事凑齐了「可靠」:
再加上端到端校验和(由目的地重算,而不信任中间任何一跳),一条不可靠的路上就架起了一条可靠的字节流。
为什么是这个分工?其一,只有两端才知道「全齐了没有」——就算每一跳都保证自己那段不出错,网关崩溃、路径切换仍会让数据丢在缝隙里,端上的检查一步也省不掉;既然端上无论如何要做一遍,中间再做就是重复劳动。其二,不记状态的中间设备便宜、快、好扩展:不必为每条连接分配内存,崩了重启不影响进行中的通信,路径改道也无所谓。这个论证十年后被 Saltzer、Reed 与 Clark 提炼成著名的端到端论证(end-to-end arguments)。
包长上限不同这道坎,论文的答案是让网关在必要时把内网包切成几片(fragmentation),每片自带足够的头部信息独立走完剩下的路,由目的端重新拼装。
为什么不在下一个网关就拼回来?那样网关得攒着半个包等齐才走——要为每个半成品分配缓冲、设超时、处理永远等不齐的情况,等于把状态又塞回中间。「目的端重组」是为保住「网关无状态」付的代价。
最后一块拼图:一台主机上同时跑着很多程序,数据到了交给谁?论文在 TCP 地址之下再引入端口(port),把一条连接标识为「两端各自的(主机地址,端口)」这一对。于是同一台机器、同一条线上,多个通信互不干扰地并行——你一边开视频会议一边下载文件靠的就是它。
要诚实地说:这不是一篇实验论文,没有基准测试,也没有性能数字。它是一份设计提案——「结果」是它后来被实现出来、并且真的跑通了。
能算验证的有三步。一是写成可实现的规范:1974 年 12 月的 RFC 675 给出第一份完整 TCP 规格说明。二是多家独立实现并互通:1970 年代中期斯坦福、BBN 与伦敦大学学院分别实现并成功对接——这证明规范足够清楚,不同的人照着写出来的东西能互相说上话。三是真正的异构演示:1977 年数据从一辆行驶中的分组无线车出发,经 ARPANET、再经大西洋卫星网抵达目的主机,三张性质截然不同的网串成一条通路、端到端没丢一个比特。
最终的「结果」是一次全网切换:1983 年 1 月 1 日,ARPANET 把旧协议 NCP 整体换成 TCP/IP。此后互联网的增长曲线,就是这篇论文最大的实验数据。
它把网络从「一张网」变成「网络的网络」,并让这张网可以无许可地生长。新建一张网不需要谁批准、不需要改动任何既有设备,接个网关、认那个统一包格式即可——Wi-Fi、蜂窝、光纤、卫星宽带都是几十年后才有的网络,却全能原样插进 1974 年这张图。
它也奠定了互联网的「沙漏细腰」:中间只有一层薄薄的、谁都认的统一包格式(后来的 IP),上面能跑任何应用,下面能垫任何链路技术。正因为腰细、腰上不带任何智能,两头才能各自疯长。
而「智能放在边缘、网络保持愚笨」从此成为互联网与电信网最根本的分野:后者把智能集中在网里、终端只是话机;前者把网络做成哑管道,把创新权交给两端的任何人。
① 一句话:用网关在边界翻译 + 一种谁都认的统一内网包与全局地址,把互不兼容的网络拼成「网络的网络」,可靠性全交给两端。
② 痛点:1974 年已有多张分组网,但包长、地址、可靠性假设、延迟全不同;统一改造在政治上不可能,逐对翻译是 n² 的死路。
③ 网关 + 封装:网关由两半构成、各属一张网,对每张网来说只是台本地主机;统一内网包嵌在各网本地包里,网关只换外层信封、内层原封不动——于是两张网都不必改动自己。
④ 地址:「网络号 + 网内标识」的两段式分层寻址,网关只看网络号就能转发;今天 IP 的前缀路由是它的直系后代。
⑤ 最关键的一刀:中间只尽力而为、网关不保存会话状态;靠端上的逐字节序号 + 累积确认 + 超时重传 + 窗口 + 端到端校验和造出可靠字节流。理由是只有两端知道「齐没齐」,且无状态的中间设备更快、更好扩展。
⑥ 配套:网关按需切片、由目的端重组(为保住网关无状态);端口让一台主机上的多个程序并行通信。
⑦ 验证:不是实验论文——靠 RFC 675 规范、斯坦福/BBN/UCL 的独立实现互通、1977 年三网演示,以及 1983 年 ARPANET 全网切换到 TCP/IP。
⑧ 影响与局限:造出互联网的「沙漏细腰」,腰上不带智能,两头才能无许可地疯长;代价是地址开得太小(8 位网络号 → IPv4 耗尽 → IPv6)、TCP 与 IP 本是一体(1978 才拆开,才有 UDP)、网关分片成包袱、只有流量控制没有拥塞控制(1986 崩溃、1988 补上)、毫无安全设计、路由留白。