好的朋友我们正式走进了互联网世界的“起源之地”。在过去的二十多段旅程里我们一直埋头于物理层和链路层的深刻细节我们见证了网线里的电信号如何被封装成帧目睹了交换机如何学习MAC地址甚至在代码中亲手构建过一个在公网“暗度陈仓”的GRE隧道。但现在我们的视线必须拉高了。我们要问一个更根本的问题为什么会有互联网它的建立到底遵循着怎样的最高纲领今天这几页书正是《TCP/IP详解》的整个大门的“基石”——第1章《概述》。它没有上来就写代码而是用哲学和设计原则为我们搭建了互联网这座宏伟教堂的骨架。这是一篇必须深刻理解才能真正理解TCP/IP为何能统治世界的奠基之作。第1章 概述一从“电路独占”到“分组自由” —— 互联网起源、8大架构原则与端到端哲学引言从“物理学”走向“社会学”前面的旅程我们像是在修路、建桥、铺设管道。而现在我们要思考的是这条路的“路规”到底是什么。要想理解TCP/IP协议簇我们首先要回答一个问题当你、我、以及地球上数十亿台设备连在一起时我们到底是怎么说上话的这不仅仅是技术问题更是一场解决“沟通问题”的社会学设计。就好比人类社会如果没有语言一切沟通都是徒劳如果没有法律和规则一切商业和交往都会陷入混乱。计算机网络也是同理“有效沟通取决于使用共同的语言”。在网络世界里这个共同的语言就叫“协议”。第一部分互联网的“胎动”——从ARPANET到全球互联网络让我们先来看看互联网的起源。在20世纪60年代以前通信领域几乎是“电话网络”一统天下。你打一个长途电话电话交换局就必须为你从上海到北京的几十条线路上专门“焊死”一条属于你的物理通道。这条通道在通话期间是绝对专用的哪怕是双方都没说话这条线也空占着别人谁都不能用。这被称为**“电路交换”Circuit Switching**。为什么电路交换失败了试想一下如果我们用电话线的方式来传输数据每一次发邮件都要先“霸占”一条完整的物理线路这不仅极度浪费资源而且极其昂贵。于是20世纪60年代一种打破常规的新思想诞生了——分组交换Packet Switching。分组的精髓不再是“一直霸占”整条线而是把你发的10MB邮件切成无数个只有几千字节大小的“小方块”我们称之为分组或包。每个小方块的头上都贴上了标签“我是第1号”“我是第2号”。这些“小方块”可以各自寻找不同的道路有的走高速公路有的走拥堵的国道甚至有的会绕路。当它们全部汇聚在目的地时再根据标签按照顺序拼接成一封完整的邮件。为什么分组交换是互联网的基石弹性如果某条线路被炸毁了小方块们会自动寻找另一条通行的路网络具有极高的生存和抗毁能力。统计复用高效如果此刻你正好在发呆没有发数据包那你所占用的网络资源带宽会被旁边正在下载电影的人“借用”。网络资源不被闲置利用率极高这就是“统计复用”的核心。在这种思想催化下ARPANET阿帕网诞生了随后演变成了我们熟知的Internet因特网即“互联网络”。第二部分互联网的八条“国策”——David Clark的体系架构原则由于计算机不只有IBM还有DEC、Xerox、甚至各种私有网络。若想让所有的不同厂家、不同型号的计算机都连在一起必须有一套统一的“交通法规”。书里引用了网络界泰斗David Clark在1988年提出的一句话这也是网络体系结构设计的最高纲领“发展一种重复利用已有的互联网络的技术。”这句话大白话翻译就是“我们不去推翻原有的世界不去消灭现有的各种不同的局域网而是用一套机制把这些已经存在的网络全部连接起来。”基于这个宏大的目标本书列出了八大核心架构原则。我们来逐一拆解看看为什么这些原则至今仍在规范着我们。【图片占位符互联网的 8 条体系结构原则表格图】此处建议插入一张对比图列出书中的8条原则1. 在网络或网关失效时持续运行。2. 支持多种通信服务。3. 容纳多种网络。4. 资源分布式管理。5. 经济性。6. 低容量主机的连接。7. 资源可计量。8. 端到端与命运共享。Internet 通信在网络或网关失效时必须能够持续这是互联网的“不死鸟”法则。网络永远不应该有一个“中央司令部”。无论哪台路由器断电数据都应能“绕道而行”。Internet 必须支持多种类型的通信服务不能只允许发文本邮件还必须支持语音、视频、流媒体等多种服务。Internet 体系结构必须容纳多种网络异构性。不管你底层的物理网络是光纤、铜线还是无线电波IP协议必须能统统把它们当作“通路”跑起来。Internet 体系结构必须允许对其资源的分布式管理去中心化。没有那个“全世界网络总局”来管理你。每个国家、每个运营商、甚至你家的路由器都可以独立管理自己管辖的这块区域。Internet 体系结构必须是经济有效的不能因为要上互联网就要把每个用户的电脑都换成“超级计算机”。接入成本必须极其低廉。Internet 体系结构必须允许低能力主机的连接包容性。即使是一台几十年前的、CPU性能极低的旧电脑也必须能接上互联网。Internet 中使用的资源必须是可统计的可计费性。用量资源要能算得清楚运营商要能根据你的流量来收钱而不是按固定总额一刀切。端到端原则与命运共享这是最深刻的一条原则我们必须专门用一章节来解释。第三部分数据报与虚电路——IP的“自由行”哲学在网络的底层逻辑里其实存在两条截然不同的路。一条是我们在前面提到的“虚电路VC”比如老旧的X.25协议另一条是互联网最终选定的“数据报”。VS对比虚电路 与 数据报虚电路这就像你坐火车。你买票时必须提前确认好你的起点、终点和座位号。沿途所有的车站路由器必须为你预先预留好资源然后在传输过程中所有的数据包都必须按部就班地走同一条预先定好的铁轨。缺点它依赖于“连接状态”。如果中途一个路由器坏了前面所有的“虚电路”都会被摧毁必须重新建立。数据报这就像你寄信。你把信数据报扔进邮筒后不需要向任何车站报备。每一封信上都独立写着“收件人地址”。信到了中转站车站路由器根据当天的拥堵情况现场决定把信发向哪条路。这一封信可能走北京下一封信可能走上海。到达目的地后再由接收方负责把顺序乱掉的信拼好。优点无连接。网络不需要存储任何关于你的“身份信息”。这样网络极其健壮哪怕中途一个路由器被炸毁只需让后面的信绕路即可。也正是“数据报”的思想使得TCP/IP协议彻底抛弃了“网络层需要承担责任保证可靠、建立虚电路”的沉重枷锁将其简化为一个极度高效、轻盈的转发系统。互联网也借此彻底战胜了复杂度极高的X.25和ATM技术成为了全球化的赢家。第四部分端到端原则与命运共享——互联网的“上帝视角”接下来我们翻到了书里极不寻常的一页——1.1.2 端到端论点与命运共享。这里引用了网络界一个极其著名的定理Saltzer, Reed, Clark 1984。这个定理深刻地影响了TCP/IP的设计。4.1 端到端原则End-to-End Principle【穿插原文 1】“只有在通信系统端角度的应用知识的帮助下才能完全和正确地实现问题中提到的功能。因此作为通信自身的一个特点不可能提供有疑问的功能。有时候通信系统提供的一个功能不完整的版本可能用于提高性能。”这句话很绕口但用大白话翻译过来就是“网络本身应该是个纯粹的‘智障管道’。”错误的理解为了保障文件传输的可靠性有人认为网络层路由器应该做数据加密、错误重传、数据排序。把网络弄得复杂无比。端到端的正确理解不要在网络内部做花哨的操作。真正需要精准保证可靠性、安全性的功能应该交到坐在网络两端的应用程序端到端自己手里。举个生动的例子假设你想把100本一模一样的书从北京运到上海。网络层的做法让中途的每一个火车站都派人用放大镜检查这100本书里有没有错别字如果发现一本有错字直接在火车站帮你去掉然后让你重发。这样做会累死火车站的员工导致转运极度缓慢。端到端原则的做法火车站IP层啥也不管书直接丢到上海。到了上海图书馆应用层/TCP层管理员发现第98本书掉了一个页码他只向北京申请重发一本“第98本”其他99本不用动。4.2 消息边界图1-1的深度拆解让我们深度审视书中那张图1-1的内容。这个图示极其精准地描绘了TCP和UDP在“消息边界”上的本质不同。【图片占位符消息边界保留与非保留机制的对比图】此处建议插入一张包含上下两半段的图示。上半段展示应用程序连续 3 次写入 H1、H2、H3经过保留消息边界的网络传输层接收方侧展示收到 3 个大小不变的数据块 H1、H2、H3。下半段展示同样的 3 次写入经过不保留消息边界的传输层接收方侧展示数据被像水流一样混合需要应用程序自己判断边界。保留消息边界如TCP流想象一下你写了三封内容不同的信H1、H2、H3。传输时这封信会被当做一股连续不断的水流。在接收方看来我不知道这一股水里哪里是“第一封信”的结束哪里是“第二封信”的开始。如果你想按封信接收你必须自己在水里面做标记应用层自己实现。不保留消息边界如UDP数据报想象一下你发三条微信消息。接收方收到的就是三条独立的消息你发的是三条他就收到三条边界绝对清晰。UDP就是这种模式。为什么TCP不保留边界因为TCP底层走的是可靠的流式传输。把数据交给TCP时它只在乎“这个字节流我能不能一五一十地传到对端”它不在乎你是发了“你好”还是“我们”它只会把它们当成长长的序列字串。如果应用层需要在TCP上面区分不同的“消息”TCP是不管的必须由应用层程序员自己去在数据里加分隔符解决。这恰恰完美印证了上面说的“端到端原则”4.3 命运共享Fate Sharing这个原则极其深刻。【穿插原文 2】“命运共享建议将所必要的状态放在通信端点这些状态用于维护一个活动的通信关联例如虚拟连接。由于这个原因导致通信失效的情况也会导致一个或更多端点失效这样显然会导致整个通信的失败。命运共享也支持一种‘带智能终端主机的哑网络’模型当前 Internet 中的矛盾是哪些功能在网络中实现哪些功能不在网络中实现。”通俗解析如果网络认为“保证连接不中断”是它自己的责任那网络就必须把“你是谁、你在跟谁说话”这种状态记在自己的路由器里。但命运共享说不把这种状态记在路由器里太危险了。一旦路由器断电记在里面的状态就全部丢失了。我们应该把控制权交还给两个端点。所以在TCP/IP协议里如果中间的网络垮了TCP连接就会“断掉”。这看起来是缺点但恰恰是优点——网络瞬间变成了**“哑网络”**。它不管你的死活它只负责传包。这样网络才能保持极高的扩展性和稳定性。这就是“命运共享”的哲学网络和设备要同生共死。你看似放弃了中间网络的可靠性你却获得了无数终端节点的绝对自由。第五部分差错控制与流量控制——“尽力而为”的极度浪漫那么当网络层完全不管数据的死活只管尽力而为时谁来保证不出错呢5.1 差错控制坏包直接被扔进垃圾桶当网络发生拥塞或者物理干扰导致数据包出现比特错误时IP层网络层提供的服务是“尽力而为Best-Effort”。什么叫尽力而为当IP层检测到数据包的校验和FCS不对或者检测到数据包损坏时它会直接把这个包扔进垃圾桶然后什么也不做继续去发下一个包。它绝对不会去费劲通知发送方“你的包坏了”更不会帮你重发。这就是“尽力而为”的核心——它不保证可靠性它只保证“我会努力往那边扔”。5.2 流量控制上游拉得太快下游拉不住怎么办在网络中经常发生一种情况发送方比如你要发送一个几百GB的超大文件的电脑速度极快咔咔咔往外丢包。但是接收方比如你朋友的老旧手机处理速度极慢根本接不住你的包。如果此时路由器不受控制接收方的内存会瞬间被填满爆掉造成大量丢包。IP层网络层会管这个事吗绝对不会。书里明确指出IP 层只负责转发流量控制是由高层也就是TCP传输层在主机端实现的。TCP在主机侧通过滑动窗口机制动态计算“发送方的速度”和“接收方的缓存大小”一旦发现对方快接不住了TCP就会主动让发送方把速度降下来。这又印证了前面提到的“端到端原则”复杂的流控制逻辑统统交给两端的操作系统去管网络只管闷头干路。第六部分设计与实现 —— 观念与实体的分野最后在书的第5页提了一个非常务实的观点体系结构Architecture和实现Implementation是两码事。体系结构这是一组抽象的设计决策、各个部件如何连接、它们应该遵守什么样的准则。就像是摩天大楼的“工程图纸”。实现这是用具体的代码、硬件去把图纸变成现实。就像造房子的砖瓦和钢筋混凝土。在计算机网络的发展史上有过无数种“理论非常完美的体系结构比如ATM、X.25”但它们的“实现”太困难成本太高最终被市场淘汰。而TCP/IP的体系结构明明看起来是“不靠谱”的因为它不做任何重传、也不保证线路可靠但由于它的实现简单、成本低廉、高度包容最终成为了全世界亿万网民共同使用的标准。这给我们在做编程和系统设计时一个极大的启示完美的理论如果不能转化为低廉、可落地的实现最终只会沦为博物馆的展品。结语从建筑图纸中看透互联网的本质今天我们没有纠结任何一行具体的代码也没有去背诵任何具体的字段。我们做了一件更加重要的事情看懂了互联网的“生存之道”。我们知道了互联网之所以能撑起几十亿台设备是因为它的根基是分组交换使得资源能被最大化利用。它的骨架是去中心化与容错任何单一节点的损坏都无法杀死整个网络。它的灵魂是“端到端原则”网络要做真正的“傻瓜”把复杂、沉重的可靠性、状态保留、消息边界的解析统统交给两端的应用程序比如浏览器、QQ、微信去自己搞定。它的运输哲学是“尽力而为”绝不把宝贵的网络资源浪费在检查错误和重传上。正是这种“极简、包容、去中心化”的互联网哲学让这场跨越半个多世纪的数字革命持续到今天。当你看到家里哪怕是最低端的路由器依然可以连接世界上最先进的云服务器时你就应该明白这正是 David Clark 所提出的“发展一种重复利用已有的互联网络的技术”的伟大胜利。