计算机网络(基础篇)
TCP/IP 网络模型
应用层(Application Layer)
应用层只需要专注于为用户提供应用功能,比如 HTTP、FTP、Telnet、DNS、SMTP等。
应用层是工作在操作系统中的用户态,传输层及以下则工作在内核态。
传输层(Transport Layer)
应用层的数据包会传给传输层,传输层是为应用层提供网络支持的。
传输层只需要服务好应用即可,它作为应用间数据传输的媒介,帮助实现应用到应用的通信,而实际的传输功能就交给下一层,也就是网络层。
TCP
- TCP 的全称叫传输控制协议(Transmission Control Protocol)。大部分应用使用的正是 TCP 传输层协议,比如 HTTP 应用层协议。
- TCP 相比 UDP 多了很多特性,比如流量控制、超时重传、拥塞控制等,这些都是为了保证数据包能可靠地传输给对方。
UDP
- UDP全称叫用户数据报协议(User Datagram Protocol)。
- UDP 只负责发送数据包,不保证数据包是否能抵达对方,但它实时性相对更好,传输效率也高。
TCP 段(TCP Segment)
当传输层的数据包大小超过 MSS(TCP 最大报文段长度) ,就要将数据包分块,这样即使中途有一个分块丢失或损坏了,只需要重新发送这一个分块,而不用重新发送整个数据包,在 TCP 协议中,我们把每个分块称为一个 TCP 段。
端口
当设备作为接收方时,传输层则要负责把数据包传给应用,但是一台设备上可能会有很多应用在接收或者传输数据,因此需要用一个编号将应用区分开来,这个编号就是端口。
由于传输层的报文中会携带端口号,因此接收方可以识别出该报文是发送给哪个应用。
网络层(Internet Layer)
- 传输层只需要服务好应用即可,它作为应用间数据传输的媒介,帮助实现应用到应用的通信,而实际的传输功能就交给下一层,也就是网络层。
IP 协议(Internet Protocol)
IP 协议会将传输层的报文作为数据部分,再加上 IP 包头组装成 IP 报文,如果 IP 报文大小超过 MTU(以太网中一般为 1500 字节)就会再次进行分片,得到一个即将发送到网络的 IP 报文。
IP 地址
网络层负责将数据从一个设备传输到另一个设备,设备有很多,因此网络层需要有区分设备的编号,一般用 IP 地址给设备进行编号。
IP 地址分成两种意义:
- 一个是网络号,负责标识该 IP 地址是属于哪个「子网」 的。
- 一个是主机号,负责标识同一「子网」下的不同主机;
在寻址的过程中,先匹配到相同的网络号(表示要找到同一个子网),才会去找对应的主机。
子网掩码
需要配合子网掩码才能算出 IP 地址的网络号和主机号。
- 比如
10.100.122.0/24
,后面的/24
表示就是255.255.255.0
子网掩码.- 255.255.255.0 二进制是「11111111-11111111-11111111-00000000」, 24 个1,为了简化子网掩码的表示,用
/24
代替255.255.255.0
。
计算网络地址和主机地址
- 将IP地址和子网掩码进行按位与运算,就可以得到网络号。
- 将子网掩码取反后与IP地址进行进行按位与运算,就可以得到主机号。
路由
- 当数据包到达一个网络节点,需要通过路由算法决定下一步走哪条路径。
- 路由器寻址工作中,就是要找到目标地址的子网,找到后进而把数据包转发给对应的网络内。
IP寻址 vs 路由
- IP 协议的寻址作用是告诉去往下一个目的地该朝哪个方向走
- 路由则是根据「下一个目的地」选择路径
- 寻址更像在导航,路由更像在操作方向盘
网络接口层(Link Layer)
生成了 IP 头部之后, 网络接口层在 IP 头部的前面加上 MAC 头部,并封装成
数据帧(Data frame) 发送到网络上。
网络接口层主要为网络层提供 「链路级别」传输 的服务,负责在以太网、WiFi 这样的底层网络上发送原始数据包,工作在网卡这个层次,使用 MAC 地址来标识网络上的设备。
以太网
以太网就是一种在「局域网」内,把附近的设备连接起来,使它们之间可以进行通讯的技术。
-
以太网在判断网络包目的地时和 IP 的方式不同,必须采用相匹配的方式才能在以太网中将包发往目的地,以太网进行通讯要用到 MAC 地址。
-
MAC 头部是以太网使用的头部,它包含了接收方和发送方的 MAC 地址等信息。可以通过 ARP 协议获取对方的 MAC 地址。
总结
TCP/IP 网络通常是由上到下分成 4 层,分别是应用层,传输层,网络层和网络接口层。
每一层的封装格式
网络接口层
的传输单位是 帧(frame)IP 层
的传输单位是 包(packet)TCP 层
的传输单位是 段(segment)HTTP
的传输单位则是 消息或报文(message)
这些名词并没有什么本质的区分,可以统称为数据包。
HTTP
1. 解析URL
- 浏览器做的第一步工作是解析 URL, 从而生成发送给 Web 服务器的请求信息。
- URL 实际上是请求服务器里的文件资源。
2. 生产 HTTP 请求信息
对 URL 进行解析之后,浏览器确定了 Web 服务器和文件名,接下来就是根据这些信息来生成 HTTP 请求消息了。
DNS(真实地址查询)
查询服务器域名对应的 IP 地址
- 通过浏览器解析 URL 并生成 HTTP 消息后,需要委托操作系统将消息发送给 Web 服务器。
委托操作系统发送消息时,必须提供通信对象的 IP 地址。
DNS 服务器,专门保存 Web 服务器域名与 IP 的对应关系。
域名的层级关系
- DNS 中的域名都是用句点来分隔的,比如
www.server.com
,这里的句点代表了不同层次之间的界限, 最后的一个点代表根域名。 - 在域名中,越靠右的位置表示其层级越高。
域名的层级关系类似一个树状结构:
- 根 DNS 服务器(.)
- 顶级域 DNS 服务器(.com)
- 权威 DNS 服务器(server.com)
域名解析的工作流程
-
浏览器会先看自身有没有对这个域名的缓存,
- 如果有,就直接返回
- 如果没有,就去问操作系统
-
操作系统也会去看自己的缓存,
- 如果有,就直接返回
- 如果没有,再去 hosts 文件看
-
hosts 文件也没有,才会去问 「本地DNS 服务器」 。
DNS 域名解析的过程,只指路不带路。
协议栈
通过 DNS 获取到 IP 后,就可以把 HTTP 的传输工作交给操作系统中的协议栈。
IP 中还包括 ICMP 协议和 ARP 协议:
ICMP
用于告知网络包传送过程中产生的错误以及各种控制信息。ARP
用于根据 IP 地址查询相应的以太网 MAC 地址。
TCP(可靠传输)
HTTP 是基于 TCP 协议传输的。
TCP 包头格式
状态位:
SYN
是发起一个连接,ACK
是回复,RST
是重新连接,FIN
是结束连接
TCP 三次握手
在 HTTP 传输数据之前,首先需要 TCP 建立连接,TCP 连接的建立,通常称为三次握手。
三次握手目的是保证双方都有发送和接收的能力。
TCP 连接状态
TCP 分割数据
TCP 报文生成
TCP 协议里面会有两个端口,
- 一个是浏览器监听的端口(通常是随机生成的)
- 一个是 Web 服务器监听的端口(HTTP 默认端口号是 80, HTTPS 默认端口号是 443)
在双方建立了连接后,TCP 报文中的数据部分就是存放 HTTP 头部 + 数据,组装好 TCP 报文之后,就需交给下面的网络层处理。
网络包的报文:
IP (远程定位)
TCP 模块在执行连接、收发、断开等各阶段操作时,都需要委托 IP 模块将数据封装成网络包发送给通信对象。
IP包头格式
IP 头部的源地址选择
假设 Web 服务器的目标地址是 192.168.10.200
:
IP 报文生成
MAC(两点传输)
生成了 IP 头部之后,接下来网络包还需要在 IP 头部的前面加上 MAC 头部。
MAC 包头格式
MAC 头部是以太网使用的头部,它包含了接收方和发送方的 MAC 地址等信息。
一般在 TCP/IP 通信里,MAC 包头的协议类型只使用:
0800
: IP 协议0806
: ARP 协议
获取对方的 MAC 地址
需要 ARP 协议帮我们找到路由器的 MAC 地址。
后续操作系统会把本次查询结果放到一块叫做 ARP 缓存的内存空间留着以后用,不过缓存的时间就几分钟。
MAC 报文生成
网卡(出口)
- 网络包只是存放在内存中的一串二进制数字信息,没有办法直接发送给对方。
- 网卡:负责将数字信息转换为电信号,使其能在网线上传输(真正的数据发送过程)。
- 控制网卡还需要靠网卡驱动程序。
- 网卡驱动获取网络包之后,会将其复制到网卡内的缓存区中,接着会在其开头加上报头和起始帧分界符,在末尾加上用于检测错误的帧校验序列。
起始帧分界符
:是一个用来表示包起始位置的标记末尾的 FCS(帧校验序列)
:用来检查包传输过程是否有损坏
最后网卡会将包转为电信号,通过网线发送出去。
交换机
交换机的设计是将网络包原样转发到目的地。交换机工作在 MAC 层,也称为二层网络设备。
交换机的包接收操作
-
电信号到达网线接口,交换机里的模块进行接收,接下来交换机里的模块将电信号转换为数字信号。
-
通过包末尾的 FCS 校验错误,如果没问题则放到缓冲区。
- 计算机的网卡本身具有 MAC 地址,并通过核对收到的包的接收方 MAC 地址判断是不是发给自己的,如果不是发给自己的则丢弃;
- 交换机的端口不核对接收方 MAC 地址,而是直接接收所有的包并存放到缓冲区中。
- 和网卡不同,交换机的端口不具有 MAC 地址。
-
查询这个包的接收方 MAC 地址是否已经在 MAC 地址表中有记录了。
交换机根据 MAC 地址表查找 MAC 地址,然后将信号发送到相应的端口。
路由器
网络包经过交换机之后,现在到达了路由器,并在此被转发到下一个路由器或目标设备。
-
基本原理:当转发包时,首先路由器端口会接收发给自己的以太网包,然后路由表查询转发目标,再由相应的端口作为发送方将以太网包发送出去。
-
包接收操作:路由器的端口都具有 MAC 地址,只接收与自身地址匹配的包,遇到不匹配的包则直接丢弃。
-
完成包接收操作之后,路由器就会去掉包开头的 MAC 头部。
-
转发操作:
-
查询路由表判断转发目标
-
找不到匹配路由时,就会选择默认路由,路由表中子网掩码为 0.0.0.0 的记录表示「默认路由」。
-
-
发送操作:
- 根据路由表的网关列判断对方的地址。
- 如果网关是一个 IP 地址,则是要转发到的目标地址,还未抵达终点,还需继续需要路由器转发。
- 如果网关为空,则 IP 头部中的接收方 IP 地址就是要转发到的目标地址,说明已抵达终点 。
- 通过 ARP 协议根据 IP 地址查询 MAC 地址,并将查询的结果作为接收方 MAC 地址。
- 在 ARP 缓存中查询,如果找不到则发送 ARP 查询请求。
- 发送方 MAC 地址字段,这里填写输出端口的 MAC 地址。还有一个以太类型字段,填写
0800
(十六进制)表示 IP 协议。 - 网络包完成后,接下来会将其转换成电信号并通过端口发送出去。
- 发送出去的网络包会通过交换机到达下一个路由器,经过层层转发之后,网络包就到达了最终的目的地。
- 根据路由表的网关列判断对方的地址。
在网络包传输的过程中,源 IP 和目标 IP 始终是不会变的,一直变化的是 MAC 地址,因为需要 MAC 地址在以太网内进行两个设备之间的包传输。
路由器与交换机的区别
- 路由器是基于 IP 设计的,俗称三层网络设备,路由器的各个端口都具有 MAC 地址和 IP 地址;
- 交换机是基于以太网设计的,俗称二层网络设备,交换机的端口不具有 MAC 地址。
服务器与客户端
- 服务器接收处理请求包:数据包抵达服务器,依次解析:
- MAC 头(匹配则接收)
- IP 头(确认协议为 TCP )
- TCP 头(校验序列号,匹配则缓存并回 ACK,结合端口号确定给 HTTP 进程 ),HTTP 进程封装网页为响应报文
- 响应报文回传客户端:响应报文添加 TCP、IP、MAC 头(源为服务器 IP,目的为客户端 IP ),经网卡、交换机、路由器跳转传输,到达客户端所在路由器后,经交换机转发给客户端。
- 客户端处理与断开连接:客户端解析数据包获取 HTTP 响应报文,交由浏览器渲染页面,之后通过 TCP 四次挥手断开连接 。
网络模型
OSI 网络模型(7 层)
开放式系统互联通信参考模型(Open System Interconnection Reference Model),也就是 OSI 网络模型,该模型主要有 7 层,分别是应用层、表示层、会话层、传输层、网络层、数据链路层以及物理层。
每一层负责的职能都不同,如下:
- 应用层,负责给应用程序提供统一的接口;
- 表示层,负责把数据转换成兼容另一个系统能识别的格式;
- 会话层,负责建立、管理和终止表示层实体之间的通信会话;
- 传输层,负责端到端的数据传输;
- 网络层,负责数据的路由、转发、分片;
- 数据链路层,负责数据的封帧和差错检测,以及 MAC 寻址;
- 物理层,负责在物理网络中传输数据帧;
TCP/IP 网络模型(4层)
Linux 系统正是按照这套网络模型来实现网络协议栈的。
TCP/IP 网络模型共有 4 层,分别是应用层、传输层、网络层和网络接口层,每一层负责的职能如下:
- 应用层,负责向用户提供一组应用程序,比如 HTTP、DNS、FTP 等;
- 传输层,负责端到端的通信比如 TCP、UDP 等;
- 网络层,负责网络包的封装、分片、路由、转发,比如 IP、ICMP 等;
- 网络接口层,负责网络包在物理网络中的传输,比如网络包的封帧、 MAC 寻址、差错检测,以及通过网卡传输网络帧等;
关系
七层和四层负载均衡,是用 OSI 网络模型来描述的,
- 七层对应的是应用层,
- 四层对应的是传输层。
Linux 网络协议栈
Linux 网络协议栈:
Linux 接收网络包的流程
- 网卡接收与数据写入:网卡通过 DMA 技术,将接收的网络包写入指定内存地址(Ring Buffer 环形缓冲区 )。
网卡:是计算机里的一个硬件,专门负责接收和发送网络包。
- 网络包已到达的初始通知方式及问题:
- 最初靠触发中断告知操作系统,即网卡收包触发中断,让系统知晓。
- 但在高性能网络场景,包数量多会频繁触发中断,使 CPU 忙于处理中断,影响系统整体效率。
- 引入 NAPI 机制优化:Linux 内核 2.6 版本引入 NAPI 机制,以混合 「中断和轮询」方式收包。
NAPI 机制核心概念:不采用中断的方式读取数据,而是首先采用中断唤醒数据接收的服务程序,然后 poll 的方法来轮询数据。
- 硬件中断处理流程:
- 网卡发硬件中断给 CPU,CPU 依中断表调用中断处理函数。
- 中断处理函数先 「暂时屏蔽中断」,让网卡下次再收到数据包直接写内存,避免 CPU 持续被中断;接着发起 「软中断」,再恢复屏蔽的中断,后续主要工作交给软中断处理函数 。
网络协议栈
- 进入网络接口层:检查报文合法性,非法则丢弃;合法则识别上层协议类型(IPv4/IPv6 等 ),去掉帧头帧尾,交给网络层。
- 到网络层:取出 IP 包,判断网络包走向;若发往本机,识别上层协议(TCP/UDP ),去掉 IP 头,交给传输层。
- 传输层:取出 TCP/UDP 头,依据四元组(源 IP、源端口、目的 IP、目的端口 )找对应 Socket,将数据放入其接收缓冲区。
- 应用层:程序调用 Socket 接口,把内核 Socket 接收缓冲区数据拷贝到应用层缓冲区,唤醒用户进程 ,至此完成网络包接收。 还提及可结合图看接收(左)与发送(右,反向流程 )流程。
Linux 发送网络包的流程
- 应用层与内核态切换及初始准备:应用程序调用 Socket 发送接口(系统调用),从用户态陷入内核态 Socket 层;内核申请
sk_buff
内存,将用户数据拷贝至sk_buff
并加入发送缓冲区 。 - 协议栈逐层处理(以 TCP 为例)
- 网络协议栈从发送缓冲区取出
sk_buff
,按 TCP/IP 协议栈从上到下处理;若为 TCP 传输,因需支持丢包重传(ACK 确认前sk_buff
不能删 ),会拷贝新sk_buff
副本用于后续发送,收到 ACK 后释放原始sk_buff
。 - 填充各层首部:依次填充 TCP 头、IP 头(网络层选取路由、填充 IP 头、netfilter 过滤、可能分片 )、帧头和帧尾(网络接口层通过 ARP 获下一跳 MAC 地址填充 ),
sk_buff
借助data
指针调整适配各层数据表示(如应用层data
、TCP 层segment
等 )。
- 网络协议栈从发送缓冲区取出
- 网卡发送及后续处理
- 网络接口层将
sk_buff
放入网卡发送队列,触发“软中断”告知驱动;驱动读取sk_buff
挂到RingBuffer
,映射到网卡可访问内存 DMA 区域后实际发送 。 - 发送完成后,网卡触发“硬中断”释放内存(
sk_buff
及RingBuffer
内存 );传输层收到 TCP 报文 ACK 应答,释放原始sk_buff
。
- 网络接口层将
发送网络数据的内存拷贝操作
- 第一次拷贝:调用发送数据系统调用时,内核申请内核态
sk_buff
,将用户待发送数据拷贝到sk_buff
并加入发送缓冲区 。 - 第二次拷贝:使用 TCP 传输协议时,从传输层进入网络层,为实现可靠传输(等待 ACK ),
sk_buff
会被克隆新副本送网络层,发送完副本释放,原始保留到收到 ACK 。 - 第三次拷贝:IP 层发现
sk_buff
大于 MTU 时,申请额外sk_buff
,将原sk_buff
拷贝为多个小sk_buff
分片发送 。