本文是网络转载原文链接:
https://www.toutiao.com/i6819...
简介
互联网是怎么构成的,又是怎么运作的?什么面试官老喜欢问 TCP/IP 网络?为什么远隔万里的计算机可以互相通信?计算机网络作为 IT 行业的基石,是工程师永远绕不开的话题。
网络的分层体系结构
计算机网络是一个非常庞大且复杂的系统,所以在设计之初就严格遵守着「分层」的设计理念。分层将庞大的问题细分为了若干个局部的小问题,具有下列好处:
分层隔离
灵活性好
易于实现和维护
能促进标准化工作
其中「标准化」是促进互联网全球化的关键,在计算机网络领域,你会听说到各种各样的协议,这些都是标准化的结果。试想,如果每个网卡厂商都使用了不同的网线接口风格,那无疑是一个灾难。
主流网络分层体系结构有两种:
◈OSI(Open Systems Interconnection Reference Model,开放系统互联基本参考模型),就是常说的七层网络模型。
◈TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/因特网协议)四层网络模型,也有人愿意归为 “五层网络模型”,以其中最重要的 TCP 协议和 IP 协议命名。
值得一提的是,由国际化标准组织制定的 OSI 模型,本来是最应该在全球范围内推广的网络模型,不过因为 OSI 的设计过于理想不合实际,再加上当时应用 TCP/IP 模型的因特网(Internet)已经覆盖了全球大部分地区。种种原因,导致 OSI 并没有取得市场化的成功,仅仅是获得了理论上的研究成果。而 TCP/IP 模型则被作为了事实上的国际标准。
TCP/IP 网络模型
请注意,计算机网络的分层体系结构虽然是抽象的,但实现则是具体的。
上图展示了 HTTP 应用数据在主机间传输的过程,首先自上而下、宏观的来看数据在分层网络模型里的流转。
应用层的 “HTTP 数据” 是实际需要被传输的数据
“HTTP 数据” 被下发到传输层,并添加上 TCP 首部成为传输层的 PDU(Protocol Data Unit,协议数据单元),称作数据段(Segment)。
数据段再被下发到网络层,添加了 IP 首部后成为网络层的 PDU,称作数据包(Packet)。
数据包再被下发到数据链路层添加了 Ethernet 首部后得到的 PDU 被称为数据帧(Frame)。
数据帧最后被下发到物理层,以 01 电信号(比特数据位)的形式在物理介质中传输。
TCP/IP 的每个层级都依赖于下层支撑,越往上就离用户越近,反正则离硬件越近。从上至下,不断为应用数据附加首部的过程称为封装,从下至上不断解析首部的过程则称为解封装。
最终在物理层传输的数据帧如上图所示,含有多个首部(Head),它们具有不同的数据结构和功能,服务于数据传输的可行性。学习计算机网络,其实就是学习各式 Head 的功能,学习每一层的核心协议以及它所解决的问题。下面继续自下而上的对数据帧进行解析,深入各层级的实现细节。
物理介质层
物理介质是连接网络终端设备(计算机、交换机、路由器)的物理手段,最常见的有网线(双绞线),除此还有光纤、无线电波等。不同的物理介质决定了电信号传输的距离、带宽、速率、抗干扰能力等性能参数。
所以物理介质层主要解决的问题是:
规范了网络终端设备之间的电气、机械、流程和功能等方面的要求
规范了电频、速率、最大传输距离和物理接口等特征
物理层所带来的最直观的好处就是,我们可以使用同一根网线插进任何品牌的计算机上。
数据链路层
上文提到,数据实际会以电信号的形式在物理介质中传输,不过单纯的 01 数字显然是没有价值的,需要为电信号进行分组和排序,以特有的组织方式来赋予其特定的含义。数据链路层为了解决这个问题先后提出过包括有 Ethernet v.2、IEEE 802.2、Internetwork 在内的多种协议,其中又以 Ethernet 协议占据主导地位。
Ethernet 协议,即以太网协议,规定了电信号的分组方式。一组电信号称为一个数据帧,数据帧又由帧首、数据和帧尾三部分组成。发送方通过物理介质把数据帧发送给接收方,接收方接收到一组电信号,就会认为是接收到了一个数据帧。
◈数据帧首部:占 14 字节,包含有目标主机网卡 MAC 地址、源主机网卡 MAC 地址以及数据帧类型标识
◈数据:从上层(网络层)传递下来的数据包,范围在 [46, 1500] 个字节之间
◈数据帧尾部:占 4 个字节,是 CRC 校验序列,用来确定数据帧在传输过程中是否有损坏
MAC 地址
在规范了电信号解读方式后,数据链路层还要解决 “主机定位” 的问题:数据帧怎么知道自己应该被哪一台主机接收呢?
以太网协议规定了接入网络的终端设备都必须安装有网络设配器(即 NIC 网卡),数据帧必须由网卡发送,再由另一张网卡接收。每张网卡都被分配一个 MAC 地址,具有全球唯一性。而数据接收方的 MAC 地址就被记录在数据帧首部。
MAC 地址为 6 字节,使用 12 个十六进制数表示,e.g. 00:01:6C:06:A6:29
◈前 6 个十六进制数为厂商编号,由 IEEE(电气和电子工程师协会)分配给厂商
◈后 6 个则为该厂商的网卡流水号,由厂商自己分配
以太网协议数据帧定位原理:有了 MAC 地址以后,以太网协议采用广播形式,将数据帧发给本地网络内所有的主机,主机在接收数据帧后会解析数据帧首部的目标主机网卡 MAC 地址,再和自身的网卡 MAC 地址对比。若相同,就接收数据帧做下一步处理。若不同,则丢弃。
而且为了增幅广播的性能和组网的灵活性,一般会在本地网络中架设交换机来支持信号转发,交换机也是数据链路层的代表设备。
数据链路层主要解决的问题是:对电信号进行分组并形成具有特定意义的数据帧,然后以广播的形式通过物理介质发送给接收方。
网络层
从理论来讲,使用 MAC 地址就可以实现定位到这里世界上任意一台计算机,前提是广播的作用域也是全球范围的,但这并不现实。MAC 地址的定位方式存在本地子网的局限性。所以除了以太网协议之外,还迫切的需要解决下列问题:
如何轻易的进行子网划分
如何隔离子网之间的广播信号
在隔离广播信号的前提下,如何保证子网之间的计算机依旧能够通信
IP 协议
IP(Internet Protocol,因特网协议)是网络层的核心协议,规定了网络层的封装规范,将上层(传输层)传递下来的数据段附加上 IP 首部封装成 IP 数据包,又称数据报文,IP 数据包同样由包首部和数据两部分组成,只是数据部分实际为传输层的数据段。
数据包首部长度为 20 字节,数据部分最大长度为 65515 字节,一个 IP 数据包总长达 65535 字节。而下层数据帧的数据部分最长为 1500 个字节,所以如果 IP 数据包的实际长度超过了 1500,就需要对 IP 数据包进行分片处理,由多个数据帧发送。
IP 数据包首部:
Version 版本号:标识 IP 地址的版本,目前有 IPv4 和 IPv6 两个版本
Header Length 首部长度:标识 IP 首部长度
Type of Service 服务类型:前 3 位标识优先级,4-7 位分别标识时延、吞吐量、可靠性、开销(一个数据包只能有一位生效)
Total Length 总长度:标识 IP 数据包总长
Identification 鉴定字段:IP 数据包的唯一标识,如果数据包被分片传输,接收方会根据分片中的该字段值来判断哪些分片属于同一个数据报,以此进行分片重组。通常的每发送一份数据包该值就会被加 1。
IP Flags 标志位:标识 IP 数据包是否被分片。
Fragment Offset 偏移量:在接收方进行分片重组时,标识分片的顺序,指明了分片起始点相对于数据包起始点的偏移量。因为 IP 协议是无连接的非可靠传输协议,所以需要该字段来应对分片传输错序的情况。
TTL 生存时间:标识生存时长,指明了数据报可以经过的路由器数量,防止丢失数据包的无休止传播。初始值由源主机设置(通常为32或64),每经过一个路由器,该字段值就会减 1。如果数据包的 TTL 减至 0,那么路由器会丢弃该数据包并发送一个 ICMP 超时消息给数据包的源主机 IP 地址。
Protocol 协议:标识数据包数据部分来自于哪个协议(ICMP/IGMP/TCP/UDP/GRE/ESP)。
Header Checksum 首部校验和:根据 IP 数据包首部计算出来的校验和
Option 选项:一个可变长的可选信息
Source Addres 源地址:IP 数据包源主机的 IP 地址
Destination Address 目标地址:IP 数据包的目标主机 IP 地址,是网关路由的关键依据。
IP 地址:因为 MAC 地址无法满足复杂的网络环境需求,所以 IP 协议制定了一套逻辑上的网络地址(IP/子网掩码)。IP 地址有 IPv4 和 IPv6 两个版本,通过子网掩码将 IP 地址分为网络号、主机号两个部分,前者标识了一个子网,后者标识了子网中的主机。如果两台主机处在同一子网,那么它们的网络号必须是相同的。IP 地址解决了 “如何轻易的进行子网划分” 的问题。
ARP 协议
引入 IP 地址后,接入网络的主机至少拥有一个 IP 地址和 MAC 地址。需要强调的是,IP 地址本质上是一个逻辑地址,为了解决上层复杂的子网架构问题而生,并不能作为最终定位主机的依据,这仍要依靠 MAC 地址来完成。因此,网络层还需要找到一种方法来完成 IP to MAC 的映射,ARP 协议应运而生。
ARP(Address Resolution Protocol,地址解析协议)提供了根据 IP 地址来获取 MAC 地址的能力,地址解析之名由此而来。
地址解析原理:主机间的通信时,ARP 协议首先会发起一个请求 IP 数据包,IP 数据包的首部包含有目标主机 IP 地址,这个数据包经由数据链路层、物理介质层,最终广播到子网内所有主机,主机接受到该 IP 数据包后解析出其首部所包含的目标主机 IP 地址,再和自身 IP 地址进行比对。若相同,则根据数据包首部包含的源主机 IP 地址将 MAC 地址返回;若不相同,则丢弃该数据包。同时 ARP 协议还会缓存一份地址映射表在本地,表记录为返回的 MAC 地址和目标主机 IP 地址。下次再需要通信时,ARP 会直接查询地址映射表以提高效率。
路由协议
通过 ARP 协议的地址解析原理不难发现,ARP 协议同样具有子网局限性。为了突破这一限制实现跨子网通信,网络层实现了路由协议。
路由协议提供了异构网(子网间)互联的能力,可以将一个子网的 IP 数据包发送到另一个子网。所谓 “路由” 即指导数据包转发的路径信息。路由协议是运行在路由器上的协议,在错综复杂的网络世界中,路由器充当了交通枢纽的角色,它会视实际的网络环境来选择最佳路径进行数据包转发,路由器是网络层的代表设备。
IP 数据包路由原理:主机间的通信时,首先会通过 IP 协议来判断两台主机是否处在同一子网。若是,直接交给 ARP 协议和以太网协议来完成子网广播。若不是,以太网协议则会将 IP 数据包发送到子网网关(一般为路由器)进行路由决策,在经过若干次网关路由转发之后,IP 数据包就进入到目标主机 IP 地址所处的子网中,最后还是通过子网广播完成主机定位。
可见,路由器和路由协议解决了 “如何隔离子网之间的广播信号” 和 “子网之间的计算机依旧能够通信” 的问题。
传输层
通过物理介质层、数据链路层和网络层的底层支撑,或者说通过 MAC 地址和 IP 地址的支撑,得以实现了主机间在全球互联网中的互联互通,所以三者也会被归纳为「基础传输层」。
不过仅仅支持 “主机定位” 依旧是不足以满足需求的,还需要完成主机上的 “应用程序定位” 才可以。因为互联网传输的数据往往是应用程序的数据,比如微信聊天,实际是两台设备上微信 APP 之间的数据传输。所以主机在接收到数据后,还需要解决:这个 IP 数据包应该交由谁来处理?就是所谓的 “应用程序定位” 问题。
对此,传输层规定为每个应用程序都指定一个特殊的 “地址” 来辅助定位,这个 “地址” 就是 —— 进程端口(Port)
传输层的主要作用就是建立进程与进程之间的通信,即 Port 到 Port 之间的数据传输,主要有 UDP 协议和 TCP 协议两种实现。如果你具有网络应用编程经验,那么你对 (IP, Port) 的组合应该不会感到陌生,这就是 Unix 系列操作系统定义的 Socket 套接字。
可用端口号在 [0, 65535] 之间,其中 [0, 1023] 属于系统端口,由操作系统原生服务进程使用,其余为用户端口,由用户自由分配。传输层的 PUD 为数据段(Segment),其首部也有 TCP 首部和 UDP 首部两种类型。
数据段首部为 8 字节,数据部分为上层应用数据占 65527 字节,总长不超过 65,535 字节,正好作为下层 IP 数据包的数据部分。
TCP 协议
TCP(Transmission Control Protocol,传输控制协议),是一种面向连接的可靠传输协议,提供可靠(无差错、不丢失、不重复、按顺序)的字节流数据传输服务。在传输效率和可靠性之间选择了后者,所以有开销大、传输速度慢的缺点。
面向连接:在使用 TCP 通信之前,需要进行 “三次握手” 建立发收双方连接,通信结束后还要进行 “四次挥手” 确保断开连接。
点对点:一条 TCP 连接只能连接两个端点。
全双工通信:允许通信双方任意时刻双向发送数据,发送方设有发送缓存,接收方设有接收缓存。
字节流传输:TCP 会将数据当作字节流进行处理,不尝试理解所传输的数据含义,仅把数据看作一连串的字节序列。
TCP 的可靠性传输具有非常复杂的实现细节,包括但不限于:
ACK 确定机制:当接收方接收到数据段后,会返回 ACK 确认
定时重发:发送方发送数据段后,会启动定时器,超时未接收到 ACK 确认,会重发该数据段
数据校验:接收方会对数据段进行数据校验,如果发现数据段有差错,会将该数据段丢弃,等待超时重传
顺序传输:TCP 字节流会为每个字节排序,确保数据传输顺序的正确性
滑动窗口:TCP 数据段长度可根据收发双方的缓存、网络等状态而调整。接收方只允许发送方发送接收缓冲区所能接纳的数据,防止缓冲区溢出
数据段首部:
Sequence Number 序列号:字节流中的每个字节都要按序编号,该字段值为本数据段数据部分的第一个字节的序号
Acknowledgment Number 确认号:确认序列号
Offset 偏移量:数据段首部的长度,字段值为首部长度除以 4
Reserved 预留:保留位,供今后使用
TCP flags 标签:标识数据段性质。
Window 窗口:标识发送者接收窗口的大小
CheckSum 校验值:用于检查数据段在传输过程中是否出现差错
Urgent Pointer 紧急指针:当字段值为 1 时生效,标识本数据段具有紧急数据
其中的 TCP Flags 字段,是非常重要的功能标识,占 8 位,分别为:
C(CWR)、E(ECE):用于支持 ECN(显示阻塞通告)
U(URGENT):当值为 1 时,标识此数据段有紧急数据(比如紧急关闭),应优先传送,要与紧急指针字段配合使用
A(ACK):仅当字段值为 1 时才有效,建立 TCP 连接后,所有数据段都必须把 ACK 字段值置为 1
P(PUSH):若 TCP 连接的一端希望另一端立即响应,PSH 字段便可以 “催促” 对方,不再等到缓存区填满才发送返回
R(RESET):若 TCP 连接出现严重差错,该字段的值置为 1,表示先断开 TCP 连接,再重连
S(SYN,Synchronize Sequence Numbers):用于建立和释放连接,当字段值为 1 时,表示建立连接。
F(FIN):用于释放连接,当字段值为 1 时,表明发送方已经发送完毕,要求释放 TCP 连接
下面以三次握手和四次挥手为例,看看数据段首部是怎么进行传输标识并以此来保存可靠性的。
三次握手:
建立连接时,客户端发送 (SYN=1,seq=x) 数据段到服务器,然后进入 SYN_SENT 状态并等待服务器确认;
服务器收到 (SYN=1,seq=x) 数据段后,返回 (ACK=1, ack=x+1, SYN=1, seq=y) 数据段,服务器进入 SYN_RECV 状态;
客户端收到服务器的 ACK 确认后,也会向服务器发送 ACK 确认 (ACK=1, ack=y+1),至此客户端和服务器都进入了 ESTABLISHED 状态。三次握手完成,TCP 连接建立成功。
为什么要使用三次握手来保证数据传输的可靠性?
“握手” 的行为实际上为了告知收发双方自己的 ISN(Initial Sequence Number,初始化序号),如上图的 seq=x 或 seq=y,这个数值会被作为建立连接之后进行顺序数据传输的依据。从数据段首部的 Sequence Number 和 Acknowledgment Number 都占 32 位可知,seq 和 ack 的取值范围均为 [0, 2^32-1],顺序循环使用。需要注意的是,seq 并非每次都是从 0 开始的,TCP 协议会以 4μs 一次的频率进行 ISN+=1 操作,以此来避免 TCP 重连时会出现同一条连接中存在两个及以上 seq 相同的包,最终导致顺序错乱。
四次挥手:
断开连接时,客户端发送 (FIN=1, seq=m) 数据段,其中 m 的数值为客户端最后一次向服务器发送的数据段的最后一个字节的序号再加上 1,客户端进入 FIN-WAIT-1 状态。
服务器接收到 (FIN=1, seq=m) 之后,返回 (ACK=1, ack=m+1, seq=n) 确认数据段,服务器进入 CLOSE-WAIT 状态。
服务器再向客户端发送 (FIN=1, seq=u, ACK=1, ack=m+1) 数据段,服务器进入 LAST-ACK 状态。
客户端接收到 (FIN=1, seq=u, ACK=1, ack=m+1) 数据段后,返回 (ACK=1, ack=u+1, seq=m+1) 确认数据段,服务器和客户端都进入 CLOSED 状态。四次挥手完成,TCP 连接就此断开。
UDP 协议
UDP(User Datagram Protocol,用户数据报协议),是一种无连接的非可靠传输层协议。UDP 不提供数据包分组、组装,不能对数据段进行排序,所以 UDP 数据段的首部非常简单。换句话说,当数据段发送出去之后,发送方是无法得知其是否完整且安全的到达了接收方的。这样的传输机制决定了它的最大优点就是快,同时也决定了它最大的缺点不可靠、不稳定。
UDP 数据段首部:
Source Port 源应用程序端口:发送方的应用程序端口
Destination Port 目的应用程序端口:接收方的应用程序端口
Length 长度:数据段的长度
Checksum 校验值:用于检查数据段在传输过程中是否出现差错
应用层
应用层是直接面向用户的,所以相对于数据传输的细节,应用层更加关注数据的表示形式,其主要工作是定义数据格式并按照相应的格式要求进行数据解读。因此,应用层定义了各种各样的协议来规范数据格式,常见的有 HTTP(万维网), FTP(文件传输), SMTP(邮件) 等等。
以互联网上应用最广泛的 HTTP(HyperText Transfer Protocol,超文本传输协议)为例,其数据首部格式如下:
如上图标记内容,HTTP 规范了定义和解读数据格式的方式:
在 Request Headers 中使用 Content-Type 表示客户端发送的数据格式类型,Accept 表示客户端期望接受的数据格式类型
在 Response Headers 中使用 Content-Type 表示服务器端响应的数据格式类型
通常 Request Accept 需要与 Response Content-Type 保持一致
总结一下,应用层的作用主要是为计算机上的应用程序提供服务,包括提供数据格式表现、数据加密、远程终端会话等应用功能。应用层无需关心数据的传输细节,这是分层设计带来的好处,程序员完全可以在不了解底层协议的前提下使用应用层的众多协议来进行工作。
**
最后
回顾总结一下:**
物理介质层:是最底层的数据传输物理媒介
数据链路层:通过 MAC 地址来定位本地子网中的主机
网络层:通过 IP 地址来定位不同子网间的主机
传输层:通过 Port 来定位到主机上的应用程序
应用层:为主机上不同的应用程序提供服务
核心协议全家福: