计算机网络

尽量保证描写的清楚,且简洁。

TCP/IP 模型

四层:

网络解析网址的方式 :

URL:协议+//+服务器名称+/.../(数据源的路径)


通俗版解析:从输入网址到网页显示的全过程


1. 第一步:浏览器解析网址(找地址)
比喻:就像你想去朋友家,但只知道小区名,不知道具体门牌号。
过程
拆解 URL:浏览器把网址拆成「域名」(如 www.example.com)和「路径」(如 /index.html``)。 • **检查缓存**:先翻自己的「小本本」(浏览器缓存)看有没有记录过这个域名的 IP 地址。 • **问操作系统**:如果小本本没记,就问电脑管家(操作系统):“你记得 www.example.com` 的地址吗?”


2. DNS 查询:全网找门牌号
比喻:打电话问 114 查号台,但需要层层转接。
过程

  1. 本地 DNS 服务器(小区物业):
    ◦ 先查自己的记录,没有就联系上级。
  2. 根 DNS 服务器(全球总台):
    ◦ 回答:“.com 的顶级 DNS 服务器地址是X.X.X.X,你问它。”
  3. 顶级域 DNS(.com 管理局):
    ◦ 回答:“example.com 的权威 DNS 服务器是Y.Y.Y.Y,你问它。”
  4. 权威 DNS 服务器(朋友小区的物业):
    ◦ 最终给出 IP 地址:“门牌号是 93.184.216.34!”
    结果:浏览器拿到 IP 地址,准备出发。

3. 建立 TCP 连接:确认对方在家
比喻:打电话给朋友,先确认他是否在线。
三次握手

  1. 你(客户端):“喂,能听到吗?”(发送 SYN 包)
  2. 朋友(服务器):“能听到,你说话吧!”(回复 SYN-ACK 包)
  3. :“好的,我要说正事了!”(发送 ACK 包)
    结果:连接建立,开始传输数据。

4. 发送 HTTP 请求:打包你的需求
比喻:写一封信,告诉朋友你要借哪本书。
内容
请求行:“GET /index.html HTTP/1.1”(我要首页)
请求头:附加信息(浏览器类型、支持的语言等)。
请求体:如果是登录请求,会包含账号密码。


5. 数据包旅行:跨城快递
比喻:把信交给快递员,经过多个中转站。
过程

  1. 封装成 TCP 包:信纸装进信封(TCP 头部),写上序号(防止丢件)。
  2. 封装成 IP 包:套上快递袋(IP 头部),写清发件人(你的 IP)和收件人(服务器 IP)。
  3. MAC 地址定位:快递员(交换机)根据门牌号(MAC 地址)送到小区门口。
  4. 路由器接力
    ◦ 小区门口快递站(路由器)检查地址:“这封信要跨省,先送到省中心!”
    ◦ 省中心再转发到目标城市,直到抵达朋友家。

6. 服务器处理:拆信并回信
比喻:朋友收到信,找到书后回寄给你。
过程
拆包:服务器一层层剥开 IP、TCP 头部,看到 HTTP 请求。
处理请求:读取 /index.html,从硬盘找到文件。
生成响应:把 HTML 内容塞进 HTTP 响应包,反向封装(TCP→IP→MAC)。
回传:按原路返回,经过路由器、交换机,最终到你的电脑。


7. 浏览器渲染:拆包裹拼图
比喻:收到回信后,把碎片拼成完整的画。
过程
接收数据包:按 TCP 序号重组文件。
解析 HTML:读取文本、图片、CSS 样式。
渲染页面:把代码变成你看到的按钮、文字、图片。


关键概念通俗解析

术语 通俗解释 类比
DNS 把网站名翻译成数字地址的电话簿 查号台(114)
TCP 确保数据完整送达的“快递保价服务” 快递员打电话确认你收到包裹
IP 地址 设备的全球唯一“门牌号” 家庭住址(XX 省 XX 市 XX 街道)
MAC 地址 设备的“身份证号”,用于同一网络内精准定位 快递柜编号(A 区 3 号柜)
路由器 跨网络转发数据的“中转站” 跨省快递分拣中心
交换机 同一网络内转发数据的“快递柜” 小区内的快递代收点

Linux 网络包收发机制

一、网络模型基础

  1. OSI 七层模型(理论模型):
    • 应用层(用户接口)
    • 表示层(数据格式转换)
    • 会话层(建立/管理连接)
    • 传输层(端到端传输)
    • 网络层(路由和寻址)
    • 数据链路层(物理寻址)
    • 物理层(比特流传输)

  2. TCP/IP 四层模型(实际实现):
    • 应用层(HTTP/FTP/DNS 等)
    • 传输层(TCP/UDP)
    • 网络层(IP/ICMP)
    • 网络接口层(以太网/WiFi)

关键区别:TCP/IP 模型将 OSI 的上三层合并为应用层,更注重实用性。Linux 系统采用 TCP/IP 模型实现。

二、数据封装过程(发送时)
以发送"Hello"字符串为例:

应用层:原始数据 "Hello"
↓ 添加TCP头(源/目标端口、序列号等)
传输层:[TCP头]+"Hello"
↓ 添加IP头(源/目标IP地址)
网络层:[IP头]+[TCP头]+"Hello"
↓ 添加帧头帧尾(MAC地址、CRC校验)
网络接口层:[帧头]+[IP头]+[TCP头]+"Hello"+[帧尾]

三、接收网络包流程

  1. 硬件接收阶段
    • 网卡通过 DMA 将数据包存入环形缓冲区(Ring Buffer)
    • 触发硬件中断通知 CPU

  2. 中断处理优化(NAPI 机制)
    • 传统方式:每个包都触发中断 → 高负载时 CPU 被频繁打断
    • NAPI 方案:
    ◦ 首次中断唤醒处理线程
    ◦ 后续采用轮询方式批量处理多个数据包
    ◦ 减少中断次数,提升吞吐量

  3. 协议栈处理

    graph TD
    A[网卡驱动] --> B[网络接口层]
    B --> C{校验检查}
    C -->|合法| D[剥离帧头帧尾]
    D --> E[网络层处理IP头]
    E --> F[传输层处理TCP/UDP头]
    F --> G[Socket接收缓冲区]
    G --> H[应用层read调用]
  4. 关键数据结构
    sk_buff:贯穿整个协议栈的核心数据结构
    • 通过指针调整实现零拷贝:

    struct sk_buff {
        unsigned char *head; // 缓冲区起始
        unsigned char *data; // 当前协议层起始
        unsigned char *tail; // 数据结束
        unsigned char *end;  // 缓冲区结束
    };
    

四、发送网络包流程

  1. 应用层发起

    send(socket_fd, buffer, len, 0); // 系统调用
    
  2. 内核处理过程
    • 创建 sk_buff 并拷贝用户数据
    • 逐层添加协议头:

    graph LR
    A[应用数据] --> B[添加TCP头]
    B --> C[添加IP头]
    C --> D[添加帧头帧尾]
  3. TCP 重传机制
    • 克隆 sk_buff 副本发送
    • 原始包保留直到收到 ACK
    • 实现可靠传输的核心机制

  4. 分片处理(MTU 限制)
    • 当 IP 包超过 1500 字节时:

    def fragment(packet):
        chunks = []
        while len(packet) > MTU:
            chunk = packet[:MTU-20]  # 保留IP头空间
            chunks.append(add_ip_header(chunk))
            packet = packet[MTU-20:]
        chunks.append(add_ip_header(packet))
        return chunks
    

五、关键性能优化点

  1. 零拷贝技术
    • sendfile 系统调用:文件→Socket 直接传输
    • 减少用户态与内核态数据拷贝

  2. 多队列网卡
    • 每个 CPU 核心绑定独立队列
    • 避免缓存行竞争

  3. TSO/GSO
    • TCP Segmentation Offload:网卡硬件分片
    • Generic Segmentation Offload:内核延迟分片

六、完整流程对比

接收流程 发送流程
1. 网卡 DMA 到 Ring Buffer 1. 应用调用 send()
2. 触发硬中断 2. 创建 sk_buff 并拷贝数据
3. ksoftirqd 软中断处理 3. 协议栈逐层封装
4. 协议栈逐层解析 4. 分片处理(如果需要)
5. 数据存入 Socket 缓冲区 5. ARP 查询下一跳 MAC
6. 应用 read()读取 6. 网卡 DMA 发送

七、常见问题解答
Q:为什么需要三次内存拷贝?
A:发送时的三次拷贝:

  1. 用户空间→内核 sk_buff
  2. TCP 重传保留副本
  3. IP 分片时产生新副本

Q:MTU 设置 1500 字节的历史原因?
A:源自早期以太网的电气特性限制,现代网络可通过 Jumbo Frame(9000 字节)提升吞吐量。

Q:如何查看协议栈统计?

netstat -s       # 统计摘要
ethtool -S eth0  # 网卡详细统计
cat /proc/net/softnet_stat # 软中断统计

HTTP

常见的状态码

1xx 类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。

2xx 类状态码表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。

  • 「200 OK」是最常见的成功状态码,表示一切正常。如果是非 HEAD 请求,服务器返回的响应头都会有 body 数据。

  • 「204 No Content」也是常见的成功状态码,与 200 OK 基本相同,但响应头没有 body 数据。

  • 「206 Partial Content」是应用于 HTTP 分块下载或断点续传,表示响应返回的 body 数据并不是资源的全部,而是其中的一部分,也是服务器处理成功的状态。

3xx 类状态码表示客户端请求的资源发生了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。

  • 「301 Moved Permanently」表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问。

  • 「302 Found」表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。

301 和 302 都会在响应头里使用字段 Location,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。

  • 「304 Not Modified」不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,也就是告诉客户端可以继续使用缓存资源,用于缓存控制。
    4xx 类状态码表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。

  • 「400 Bad Request」表示客户端请求的报文有错误,但只是个笼统的错误。

  • 「403 Forbidden」表示服务器禁止访问资源,并不是客户端的请求出错。

  • 「404 Not Found」表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。

5xx 类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。

  • 「500 Internal Server Error」与 400 类型,是个笼统通用的错误码,服务器发生了什么错误,我们并不知道。

  • 「501 Not Implemented」表示客户端请求的功能还不支持,类似“即将开业,敬请期待”的意思。

  • 「502 Bad Gateway」通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。

  • 「503 Service Unavailable」表示服务器当前很忙,暂时无法响应客户端,类似“网络服务正忙,请稍后重试”的意思。

常见字段:

GET(从服务器获取指定的资源) 和 POST 请求(根据请求负荷(报文 body)对指定的资源做出处理)

HTTP 缓存

HTTP 缓存

相对来说后者可以更加准确地判断文件内容是否被修改,避免由于时间篡改导致的不可靠问题。

HTTP 特性

HTTP 特性:( HTTP/1.1,HTTP/2.0,HTTP/3.0)

HTTP1.1 相比 HTTP1.0:

性能改进:

缺点:

HTTP2 相比 HTTP1.1

HTTP/2 协议是基于 HTTPS 的,所以 HTTP/2 的安全性也是有保障的。

性能改进:

HPACK 算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。

缺点:

HTTP3.0 的优化

特点:

HTTP1.1 如何优化

提升性能的方式

HTTPS

与 HTTP 的区别:

解决"不安全"的方式:

HTTPS 建立连接过程:

TLS 协议建立的详细流程如下:

  1. ClientHello

    • 客户端向服务器发起加密通信请求,发送 ClientHello 消息。
    • 主要信息包括:
      • 支持的 TLS 协议版本(如 TLS 1.2)。
      • 客户端生成的随机数(Client Random),用于后续生成会话秘钥。
      • 支持的密码套件列表(如 RSA 加密算法)。
  2. ServerHello

    • 服务器收到请求后,回应 ClientHello,发送 ServerHello 消息。
    • 主要内容包括:
      • 确认支持的 TLS 协议版本。
      • 服务器生成的随机数(Server Random),也用于生成会话秘钥。
      • 确认的密码套件列表。
      • 服务器的数字证书。
  3. 客户端回应

    • 客户端通过 CA 公钥验证服务器的数字证书。
    • 如果证书有效,客户端提取服务器公钥,用其加密以下信息并发送给服务器
      • 一个随机数(pre-master key)。
      • 加密通信算法改变通知,表示后续信息将使用会话秘钥加密。
      • 客户端握手结束通知,连同数据摘要供服务器校验。
    • 三个随机数(Client Random、Server Random、pre-master key)用于生成会话秘钥。
  4. 服务器的最后回应

    • 服务器用协商的加密算法计算会话秘钥。
    • 向客户端发送最后的信息:
      • 加密通信算法改变通知。
      • 服务器握手结束通知,连同数据摘要供客户端校验。

整个 TLS 握手结束后,客户端与服务器开始使用会话秘钥进行加密通信,内容以普通 HTTP 协议方式传输。

数字证书签发和验证流程:

../../../../ZZZ-Misc/Z-Attachment/images/Pasted image 20250311135642.png

如何保证数据完整性?

分为握手协议和记录协议两层:

具体过程如下:

记录协议完成后,最终的报文数据将传递到传输控制协议 (TCP) 层进行传输。

HTTPS 一定可靠吗?

HTTPS 协议本身到目前为止还是没有任何漏洞的,即使你成功进行中间人攻击,本质上是利用了客户端的漏洞(用户点击继续访问或者被恶意导入伪造的根证书),并不是 HTTPS 不够安全。

客户端通过浏览器向服务端发起 HTTPS 请求时,被「假基站」转发到了一个「中间人服务器」,于是客户端是和「中间人服务器」完成了 TLS 握手,然后这个「中间人服务器」再与真正的服务端完成 TLS 握手。

从客户端的角度看,其实并不知道网络中存在中间人服务器这个角色。那么中间人就可以解开浏览器发起的 HTTPS 请求里的数据,也可以解开服务端响应给浏览器的 HTTPS 响应数据。相当于,中间人能够 “偷看” 浏览器与服务端之间的 HTTPS 请求和响应的数据。

CA 被攻破或错误签发证书时(或电脑中病毒,被恶意导入了中间人的根证书),这种情况下,浏览器是不会弹出证书存在问题的风险提醒的。

抓包工具如何截取 Https 数据?
使用抓包工具进行 HTTPS 抓包的时候,需要在客户端安装 Fiddler 的根证书,这里实际上起认证中心(CA)的作用

抓包工具能够抓包的关键是客户端会往系统受信任的根证书列表中导入抓包工具生成的证书,而这个证书会被浏览器信任,也就是抓包工具给自己创建了一个认证中心 CA,客户端拿着中间人签发的证书去中间人自己的 CA 去认证,当然认为这个证书是有效的。

如何避免被截取数据?

*不去点击非法网站即可*

通过 HTTPS 双向认证来避免这种问题.

一般我们的 HTTPS 是单向认证,客户端只会验证了服务端的身份,但是服务端并不会验证客户端的身份。

如果用了双向认证方式,不仅客户端会验证服务端的身份,而且服务端也会验证客户端的身份。服务端一旦验证到请求自己的客户端为不可信任的,服务端就拒绝继续通信,客户端如果发现服务端为不可信任的,那么也中止通信。

HTTPS RSA 握手