我们的计算机和一个巨大的分布式网络连在一起,这个网络叫做互联网,互联网由无数互联设备组成。
计算机为了获取互联网上的资源,首先要连到局域网(LAN),家庭中的 WiFi 路由器连着的所有设备组成了局域网。
局域网再连到广域网(Wide Area Network——WAN),WAN 的路由器一般属于你的“互联网服务提供商”(Internet Service Provider——ISP),比如 Comcast,AT&T 和 Verizon 这些公司。
在广域网里,先连到一个区域性路由器,这个路由器可能覆盖一个街区。然后连到一个更大的WAN,可能覆盖整个城市。
可能再跳几次,但最终会到达互联网主干(the backbone of the internet),互联网主干由一群超大型,带宽超高路由器组成。
为了从互联网获取资源,数据包(packet)要先到互联网主干,沿着主干到达有对应资源的服务器,数据包从我们的计算机跳到有资源的服务器可能要跳个10次,先跳4次到达互联网主干,2次穿过主干,主干出来可能再跳4次,然后到达服务器。如果使用 Windows,Mac OS 或 Linux 操作系统,可以用 traceroute 来看跳了几次。
互联网是一个巨型分布式网络,会把数据拆成一个个数据包来传输,如果要发的数据很大,数据会被拆成多个小数据包。数据包(packet)想在互联网上传输要符合“互联网协议”(Internet Protocol——IP)的标准。
因为 IP 是一个非常底层的协议,数据包的头部(前面)只有目标地址,头部存“关于数据的数据”,也叫元数据(metadata),这意味着当数据包到达对方电脑,对方不知道把包交给哪个程序,因此需要在 IP 之上开发更高级的协议。
这些协议里最简单最常见的叫“用户数据报协议”(User Datagram Protocol——UDP)。UDP 也有头部,这个头部位于数据前面,头部里包含有用的信息,信息之一是端口号,每个想访问网络的程序都要向操作系统申请一个端口号,例如 Skype 会申请端口 3478,当一个数据包到达时,接收方的操作系统会读 UDP 头部,读里面的端口号,如果看到端口号是 3478,就会把数据包交给 Skype。
总结:IP 负责把数据包送到正确的计算机,UDP 负责把数据包送到正确的程序。UDP 头部里还有“校验和”,用于检查数据是否正确,正如“校验和”这个名字所暗示的一样,检查方式是把数据求和来对比。例如,在发送数据包前,电脑会把所有数据加在一起算出“校验和”,在 UDP 中“校验和”以16位形式存储,如果算出来的和超过了16位所能表示的最大值,高位数会被扔掉,保留低位;当接收方电脑收到这个数据包,它会重复这个步骤把所有数据加在一起,如果结果和头部中的校验和一致则代表一切正常,如果不一致则是数据被损坏了,也许是传输时碰到了功率波动,或者是电缆出现了故障。
Unfortunately,UDP 不提供数据修复或者数据重发的机制,接收方知道数据损坏后一般只是扔掉,而且 UDP 无法得知数据包是否到达,发送方发了之后无法知道数据包是否到达目的地。这些特性似乎很糟糕,但是有些程序不在意这些问题,因为 UDP really simple and fast。
要实现所有数据必须到达的美好愿望,就需要用“传输控制协议”(Transmission Control Protocol——TCP)。TCP 和 UDP 一样,头部也在存数据前面,因此人们称这个组合为 TCP/IP。
就像 UDP 一样,TCP 头部也有端口号和校验和,但是 TCP 有更高级的功能,介绍重要的几个:
TCP 数据包有序号:15号之后是16号,16号之后是17号,以此类推,发上百万个数据包也是 possible 的。序号使接收方可以把数据包排成正确顺序,即使到达时间不同,哪怕到达顺序是乱的,TCP 协议也能把顺序排对。
TCP 要求接收方的电脑收到数据包并且校验和检查无误之后(数据没有损坏)给发送方发一个确认码(acknowledgement——ACK),表示收到了。得知上一个数据包成功抵达后,发送方会发下一个数据包,假设这次发出去之后没有收到确认码,那肯定是哪里出现了错误,如果过了一定时间还没有收到确认码,发送方会再发一次。注意:数据包可能确实到达了,只是确认码延误了很久或者是传输中丢失,但是由于收件方有序列号,如果收到重复的数据包就会 be discarded。
TCP 不是只能一个包一个包发送,可以同时发多个数据包,收到多个确认码,这大大增加了效率,不用浪费时间等待确认码。
Interestingly,确认码的成功率和来回时间可以推测网络的拥堵程度,TCP 用这个信息来调整同时发包的数量,解决拥堵问题。
TCP 可以处理乱序和丢失数据包,丢了就重新发送,还可以根据拥挤情况自动调整传输率。
TCP 最大的缺点是确认码数据包把数量翻了一倍,但是并没有传输更多的信息。有时候这种代价是不值得的,特别是对时间要求很高的程序,例如在线射击游戏。
当计算机访问一个网站时需要两个东西:IP 地址(IP address)和端口号(port)。例如 172.217.7.238 的 80 端口是谷歌的 IP 地址和端口号。事实上可以输入到浏览器里,然后直接进入谷歌首页。有了这两个东西就能访问正确的网站,但是记一长串数字很烦,google.com 比一长串数字好记,所以互联网有个特殊服务,负责把域名和 IP 地址一一对应,就像是专门为互联网的电话簿,称为“域名系统”(Domain Name System——DNS),它的运作原理:在浏览器里输入 youtube.com,浏览器会去问 DNS 服务器它的 IP 地址是多少,一般 DNS 服务器是互联网供应商提供的,DNS 会查表,如果域名存在就会返回对应的 IP 地址,如果是乱敲出来的一个网站则很可能会看到 DNS 错误,因为那个网站不存在,所以 DNS 无法返回给你一个 IP 地址,如果输入的是有效地址,DNS 按理会返回一个地址,然后浏览器会给这个 IP 地址发 TCP 请求。
如今有三千万个注册域名,所以为了更好管理,DNS 不是存成一个超级长的列表,而是存成树状结构。顶级域名(Top Level Domains——TLD)在最顶部,比如 .com 和 .gov;下一层是二级域名(second level domains),比如 .com 下面有 google.com 等等;再下一层叫子域名(subdomains),比如 images.google.com 等等。这些数据散布在很多 DNS 服务器上,不同服务器负责树的不同部分。
线路里的电信号以及无线网络里的无线信号,这些叫做“物理层”(physical layer),而“数据链路层”(data link layer)负责操控“物理层”,数据链路层包括:媒体访问控制地址(MAC),碰撞检测,指数退避,以及其他一些底层协议,再上一层是“网络层”(network layer),负责各种报文交换和路由,“传输层”(transport layer)里一大部分包括 UDP 和 TCP 这些协议,负责在计算机之间进行点到点的传输,而且还会检测和修复错误,“会话层”(session layer)会使用 TCP 和 UDP 来创建连接,传递信息,然后关掉连接,这一整套叫做“会话”,查询 DNS 或看网页时就会发生这一套流程。
这是开放式系统互联通信参考模型(Open System Interconnection model——OSI)的底下5层,这个概念性框架把网络通信划分成多层,每一层处理各自的问题。如果不分层,直接从上到下捏在一起实现网络通信是完全不可能的。抽象使得科学家和工程师能分工同时改进多个层,不被整体复杂度难倒。
OSI 模型还有两层,“表示层”(presentation layer)和“应用程序层”(application layer),其中有浏览器,Skype,HTML解码等等。