🟣 计算机网络模型¶
约 2986 个字 1 张图片 预计阅读时间 15 分钟
OSI 的 7 层网络模型?¶
- 应用层:确定 进程之间通信的性质 以及满足用户需要以及提供网络和用户应用,为应用程序提供服务
- 表示层:主要解决用户信息的语法表示问题
- 会话层:会话层就是 负责建立、管理和终止表示层实体之间的通信会话
- 传输层:实现网络不同主机上的用户进程之间的数据通信
- 网络层:本层通过 IP 寻址来建立两个节点之间的连接,为源端的运输层送来的分组,选择合适的路由和交换节点
- 数据链路层:将上层数据封装成帧,用 MAC 地址访问媒介,并由错误检测和修正
- 物理层:设备之间比特流的传输
TCP/IP 的 4 层网络模型?¶
- 应用层:确定 进程之间通信的性质 以及满足用户需要以及提供网络和用户应用,为应用程序提供服务
- 传输层:实现网络不同主机上的用户进程之间的数据通信
- 网络层:本层通过 IP 寻址来建立两个节点之间的连接,为源端的运输层送来的分组,选择合适的路由和交换节点
- 数据链路层:将上层数据封装成帧,用 MAC 地址访问媒介,并由错误检测和修正
5 层因特网协议栈?¶
- 应用层:确定 进程之间通信的性质 以及满足用户需要以及提供网络和用户应用,为应用程序提供服务
- 传输层:实现网络不同主机上的用户进程之间的数据通信
- 网络层:本层通过 IP 寻址来建立两个节点之间的连接,为源端的运输层送来的分组,选择合适的路由和交换节点
- 数据链路层:将上层数据封装成帧,用 MAC 地址访问媒介,并由错误检测和修正
- 物理层:设备之间比特流的传输
从键入网址到网页显示期间发生了什么¶
- 解析 URL 生成 http 请求:获取 URL 代表的域名,把它填充到请求头中的 host 字段中并生成 http 请求
- 通过 DNS 协议解析出 IP 地址:浏览器首先查询本地的缓存,如果没有的话查询 hosts 文件。如果仍然没有,再向本地的 DNS 服务器查询。如果本地 DNS 服务器没有结果,它将向递归 DNS 服务器发起查询,递归服务器会通过迭代查询向根域名服务器、顶级域名服务器和权威域名服务器请求最终的解析结果,最后缓存在 DNS 本地服务器
- DNS 获取到 IP 地址以后把 HTTP 的传输工作交给协议栈来进行处理:通过调用 socket 函数,由用户态进入内核态,接下来就是数据传输的过程
-
TCP:
-
三次握手:
- SYN:客户端发送一个 SYN(同步)包到服务器,表示请求建立连接
- SYN-ACK:服务器收到 SYN 包后,回复一个 SYN-ACK(同步-确认)包,表示同意建立连接
- ACK:客户端收到 SYN-ACK 包后,回复一个 ACK(确认)包,连接建立
-
TLS 握手:
- 客户端问候:客户端发送一个 ClientHello 消息,包含支持的加密算法、TLS 版本等信息
- 服务器问候:服务器回复一个 ServerHello 消息,选择加密算法和 TLS 版本,并发送服务器证书
- 证书验证:客户端验证服务器证书的有效性
- 密钥交换:客户端生成一个随机数,用服务器的公钥加密后发送给服务器,服务器用私钥解密,生成会话密钥
- 完成握手:双方使用会话密钥加密通信,握手完成
-
-
连接成功后发送 HTTP 请求:
- 构建请求:浏览器构建一个 HTTP 请求,包括请求行(如 GET / HTTP/1.1)、请求头(如 Host: www.example.com)和可选的请求体(如 POST 请求的数据)
- 发送请求:浏览器通过建立的 TCP 连接将 HTTP 请求发送到服务器
- 浏览器发送的 HTTP 请求报文经传输层被 封装进 TCP 数据包,添加 TCP 头部信息,包括源端口、目标端口、序号等信息
- 每个 TCP 数据包会经过网络层被 封装成 IP 数据包,添加 IP 头部,包括源 IP 地址和目标 IP 地址,再进行路由的分组和转发
- 网络接口层 将 IP 数据包封装成数据帧,在数据链路层添加头部和尾部,包括源 MAC 地址和目标 MAC 地址(MAC地址是网络层的 ARP 协议根据 IP 地址查询出来的),数据帧在物理层通过物理介质(光纤、网线等)以比特流的形式进行传输
-
服务器处理请求:
- 接收请求:服务器接收到 HTTP 请求后,根据物理层、数据链路层、网络层、传输层和应用层的顺序将数据进行反向解析,得到最终只含有应用数据的信息,根据端口信息交由具体的程序进行处理
- 请求解析:服务器解析请求行、请求头和请求体
- 路由处理:服务器根据请求的路径和参数,确定处理请求的逻辑
- 业务逻辑:服务器执行相应的业务逻辑,可能涉及读取文件、查询数据库、调用其他服务等
- 生成响应:服务器生成一个 HTTP 响应,包括状态行(如 HTTP/1.1 200 OK)、响应头(如 Content-Type: text/html)和响应体(如 HTML 内容)
-
浏览器接收响应:
- 接收响应:浏览器接收到服务器的 HTTP 响应
- 解析响应:浏览器解析响应头和响应
-
渲染页面:
- 解析 HTML:
- 构建 DOM 树:浏览器解析 HTML 文档,构建 DOM 树(Document Object Model)
- 处理脚本:如果遇到 \<script> 标签,浏览器会暂停解析,执行脚本。脚本可能会修改 DOM 树
- 解析 CSS:
- 构建 CSSOM 树:浏览器解析 CSS 文件和内联样式,构建 CSSOM 树(CSS Object Model)
- 解析 JavaScript:
- 执行脚本:浏览器解析和执行 JavaScript 代码,JavaScript 代码可能会修改 DOM 树和 CSSOM 树
- 构建渲染树:
- 结合 DOM 和 CSSOM:浏览器将 DOM 树和 CSSOM 树结合,构建渲染树
- 布局(Layout):
- 计算布局:浏览器计算每个元素的大小和位置
- 绘制(Painting):
- 绘制元素:浏览器将元素绘制到屏幕上
- 解析 HTML:
-
处理资源请求:
- 发现资源:在解析 HTML 的过程中,浏览器会发现需要加载的资源(如图片、CSS 文件、JavaScript 文件等)
- 发送请求:浏览器会并行发送请求,加载这些资源
- 重复解析和渲染:浏览器重复上述的解析和渲染过程,直到所有资源加载完成
-
用户交互:
- 用户操作:页面加载完成后,用户可以与页面进行交互(如点击按钮、输入表单等)
- 事件处理:浏览器会根据用户的操作,触发相应的事件处理程序,更新页面内容
Linux 如何收网络包?¶
- 网卡收到网络包后通过 DMA 技术将网络包写入到 Ring Buffer 环形缓冲区
- 现代 Linux 通常通过 NAPI 机制 对接受数据的服务程序进行中断唤醒,通过 poll 的方法轮询数据,即网卡向 CPU 发起硬件中断,当 CPU 收到硬件中断请求后根据中断表调用已经注册的中断处理函数
- 首先进行 关中断:硬件中断函数会首先通知网卡在下次有数据时直接写入内存并恢复中断屏蔽,进入 软中断
- 内核中的 ksoftirqd 线程专门负责软中断的处理,当 ksoftirqd 内核线程收到软中断后就会轮询处理数据
- ksoftirqd 线程 会从 Ring Buffer 中获取⼀个数据帧,用 sk_buff 表示,从而可以作为一个网络包交给网络协议栈进行逐层处理
- 首先进入到 网络接口层,在这⼀层会检查报⽂的合法性,如果不合法则丢弃,合法则会找出该网络包的上层协议的类型,然后交给网络层
- 网络层:取出 IP 包,判断网络包下一步的走向,比如是交给上层处理还是转发出去。当确认这个网络包要发送给本机后会从 IP 头部查看上一层协议的类型是 TCP 还是 UDP,接着去掉 IP 头,交给传输层
- 传输层:取出 TCP 头或 UDP 头,根据四元组「源 IP、源端口、目的 IP、目的端口」 作为标识,找出对应的 Socket,并把数据放到 Socket 的接收缓冲区
- 应用层:程序调用 Socket 接口,将内核的 Socket 接收缓冲区的数据「拷贝」到应用层的缓冲区,然后唤醒用户进程
Linux 如何发网络包?¶
- 首先应用程序 调用 Socket 发送数据包的接口,由于这个是系统调用,所以会从用户态陷入到内核态中的 Socket 层,内核会申请一个内核态的 sk_buff 内存,将用户待发送的数据拷贝到 sk_buff 内存,并将其加入到发送缓冲区
- 接下来网络协议栈从 Socket 发送缓冲区中 取出 sk_buff,并按照 TCP/IP 协议栈从上到下逐层处理。如果使用的是 TCP 传输协议发送数据,那么先 拷贝一个新的 sk_buff 副本
- 接着对 sk_buff 填充 TCP 头。sk_buff 可以表示各个层的数据包,在应用层数据包叫 data,在 TCP 层我们称为 segment,在 IP 层我们叫 packet,在数据链路层称为 frame
- 网络层:选取路由(确认下一跳的 IP)、填充 IP 头、netfilter 过滤、对超过 MTU 大小的数据包进行分片。处理完这些工作后会交给网络接口层处理
- 网络接口层:通过 ARP 协议获得下一跳的 MAC 地址,然后对 sk_buff 填充帧头和帧尾,接着将 sk_buff 放到网卡的发送队列中
- 当收到这个 TCP 报文的 ACK 应答时 传输层就会释放原始的 sk_buff
发送网络数据涉及几次内存拷贝?¶
三次:
- 调用发送数据的系统调用时 内核会申请一个内核态的 sk_buff 内存,将用户待发送的数据拷贝到 sk_buff 内存,并将其加入到发送缓冲区
- 在使用 TCP 传输协议的情况下,从传输层进入网络层时每一个 sk_buff 都会被克隆一个新的副本出来。副本 sk_buff 会被送往网络层,等它发送完的时候就会释放掉,然后原始的 sk_buff 还保留在传输层,目的是为了实现 TCP 的可靠传输,等收到这个数据包的 ACK 时,才会释放原始的 sk_buff
- 当 IP 层发现 sk_buff 大于 MTU 时才需要进行。会再申请额外的 sk_buff 并将原来的 sk_buff 拷贝为多个小的 sk_buff