图解网络是怎样连接的
Nexmoe
浏览器生成消息 —— 探索浏览器内部
HTTP 请求
三次握手见后图
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#F0F4FC',
'primaryTextColor': '#1F2329',
'primaryBorderColor': '#000000',
'lineColor': '#888888',
'tertiaryColor': '#F5F6F7',
'tertiaryBorderColor': '#F5F6F7',
'tertiaryTextColor': '#00A4FF',
'noteBkgColor': '#FEF1CE',
'noteBorderColor': '#FEF1CE',
'noteTextColor': '#1F2329'
}
}
}%%
sequenceDiagram
participant 用户 as 用户/浏览器
participant DNS as DNS服务器
participant 服务器 as Web服务器
用户->>用户: 1. 输入URL或点击链接
用户->>DNS: 2. DNS查询域名
DNS->>用户: 3. 返回IP地址
用户->>服务器: 4. 建立TCP连接<br/>(三次握手)
服务器->>用户: 5. 确认连接建立
Note over 用户,服务器: 如果是HTTPS,还需要TLS握手
用户->>服务器: 6. 发送HTTP请求<br/>(GET/POST等)
Note right of 服务器: 请求包含:<br/>- 请求方法<br/>- URL路径<br/>- 请求头<br/>- 请求体(如有)
服务器->>服务器: 7. 处理请求<br/>(路由、业务逻辑等)
服务器->>用户: 8. 返回HTTP响应
Note left of 用户: 响应包含:<br/>- 状态码<br/>- 响应头<br/>- 响应体
用户->>用户: 9. 解析响应内容<br/>渲染页面
用户->>服务器: 10. 关闭连接<br/>(或保持连接复用)
DNS 服务
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#F0F4FC',
'primaryTextColor': '#1F2329',
'primaryBorderColor': '#000000',
'lineColor': '#888888',
'tertiaryColor': '#F5F6F7',
'tertiaryBorderColor': '#F5F6F7',
'tertiaryTextColor': '#00A4FF',
'noteBkgColor': '#FEF1CE',
'noteBorderColor': '#FEF1CE',
'noteTextColor': '#1F2329'
}
}
}%%
sequenceDiagram
participant 用户 as 用户/浏览器
participant 本地DNS as 本地DNS服务器<br/>(ISP提供·递归解析器)
participant 根DNS as 根DNS服务器<br/>(全球13台·顶级管理)
participant 顶级DNS as 顶级域DNS服务器<br/>(.com/.cn/.org等)
participant 权威DNS as 权威DNS服务器<br/>(域名所有者)
Note over 用户,权威DNS: DNS 分层查询架构 (以查询 www.example.com 为例)
用户->>本地DNS: 1. 递归查询请求<br/>www.example.com
Note over 本地DNS: 检查多级缓存<br/>• 本地缓存<br/>• 操作系统缓存<br/>• 浏览器缓存
alt 缓存命中
Note over 本地DNS: 缓存有效<br/>(TTL未过期)
本地DNS->>用户: 直接返回IP地址<br/>192.168.1.100
else 缓存未命中 - 开始分层查询
Note over 本地DNS,权威DNS: 迭代查询过程 (互相接力)
本地DNS->>根DNS: 2. 查询 www.example.com<br/>在哪个顶级域?
Note right of 根DNS: 全球13台根服务器<br/>管理所有顶级域
根DNS->>本地DNS: 3. 请找 .com 域服务器<br/>IP: 192.5.6.30
本地DNS->>顶级DNS: 4. 查询 example.com<br/>的权威服务器在哪?
Note right of 顶级DNS: .com域管理<br/>• 负责所有.com域名<br/>• 存储下级域服务器信息
顶级DNS->>本地DNS: 5. example.com权威服务器<br/>IP: 198.51.100.1
本地DNS->>权威DNS: 6. 查询 www.example.com<br/>的具体IP地址
Note right of 权威DNS: 最终解析<br/>• 域名所有者管理<br/>• 存储实际IP映射
权威DNS->>本地DNS: 7. 返回最终IP<br/>192.168.1.100
Note over 本地DNS: 缓存策略<br/>• 根据TTL缓存<br/>• 减少重复查询<br/>• 提高响应速度
本地DNS->>用户: 8. 返回解析结果<br/>192.168.1.100
end
Note over 用户: 使用IP地址<br/>建立HTTP连接<br/>访问目标网站
Note over 用户,权威DNS: DNS优化机制<br/>• 缓存机制: 减少重复查询<br/>• 负载均衡: 多台服务器分担<br/>• 就近原则: 选择最近的服务器
委托协议栈发送消息
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#F0F4FC',
'primaryTextColor': '#1F2329',
'primaryBorderColor': '#000000',
'lineColor': '#888888',
'tertiaryColor': '#F5F6F7',
'tertiaryBorderColor': '#F5F6F7',
'tertiaryTextColor': '#00A4FF',
'noteBkgColor': '#FEF1CE',
'noteBorderColor': '#FEF1CE',
'noteTextColor': '#1F2329'
}
}
}%%
sequenceDiagram
participant 浏览器 as 浏览器应用<br/>(用户程序)
participant Socket as Socket API<br/>(系统调用接口)
participant 协议栈 as 协议栈<br/>(操作系统内核)
participant 应用层 as TCP/IP协议栈<br/>应用层
participant 传输层 as TCP/IP协议栈<br/>传输层(TCP)
participant 网络层 as TCP/IP协议栈<br/>网络层(IP)
participant 链路层 as TCP/IP协议栈<br/>数据链路层
participant 网卡 as 网络接口<br/>(物理层)
Note over 浏览器,网卡: 浏览器委托操作系统协议栈发送HTTP消息的完整过程
rect rgb(255, 248, 240)
Note over 浏览器,Socket: 第一步:应用程序委托操作系统
浏览器->>Socket: 1. 创建Socket<br/>socket(AF_INET, SOCK_STREAM, 0)
Note right of Socket: Socket API作用:<br/>• 应用与协议栈的接口<br/>• 封装复杂的网络操作<br/>• 提供统一的编程接口
Socket->>协议栈: 2. 分配Socket描述符<br/>返回文件描述符
协议栈->>浏览器: 3. 返回Socket句柄<br/>用于后续通信
end
rect rgb(240, 248, 255)
Note over 浏览器,Socket: 第二步:建立连接
浏览器->>Socket: 4. 建立连接<br/>connect(sockfd, server_addr)
Socket->>协议栈: 5. 委托协议栈建立连接<br/>目标IP+端口
Note right of 协议栈: 协议栈执行TCP三次握手<br/>建立可靠连接通道
协议栈->>浏览器: 6. 连接建立成功通知
end
rect rgb(248, 255, 248)
Note over 浏览器,网卡: 第三步:发送数据 - 协议栈分层处理
浏览器->>Socket: 7. 发送HTTP请求<br/>send(sockfd, http_data, len)
Socket->>协议栈: 8. 将数据交给协议栈处理
Note over 协议栈: 协议栈接管数据处理<br/>按照TCP/IP模型分层处理
协议栈->>应用层: 9. 应用层不处理<br/>(HTTP已在浏览器完成)
应用层->>传输层: 10. 传输层处理<br/>添加TCP头部
Note right of 传输层: TCP头部包含:<br/>• 源端口、目标端口<br/>• 序列号、确认号<br/>• 窗口大小、校验和<br/>• 标志位等
传输层->>网络层: 11. 网络层处理<br/>添加IP头部
Note right of 网络层: IP头部包含:<br/>• 源IP、目标IP<br/>• 版本、头长度<br/>• 生存时间TTL<br/>• 协议类型等
网络层->>链路层: 12. 数据链路层处理<br/>添加以太网头部
Note right of 链路层: 以太网头部包含:<br/>• 源MAC、目标MAC<br/>• 帧类型<br/>• 帧校验序列FCS<br/>• 前导码等
链路层->>网卡: 13. 交给网卡发送<br/>完整的网络帧
Note right of 网卡: 物理层处理:<br/>• 数字信号→模拟信号<br/>• 通过网线/无线发送<br/>• 处理物理传输细节
end
rect rgb(255, 240, 245)
Note over 浏览器,网卡: 第四步:发送完成反馈
网卡->>协议栈: 14. 发送完成通知<br/>硬件中断
协议栈->>Socket: 15. 更新Socket状态<br/>发送缓冲区状态
Socket->>浏览器: 16. 返回发送结果<br/>成功发送的字节数
end
Note over 浏览器,网卡: 关键理解点:<br/>• 浏览器只需调用简单的Socket API<br/>• 协议栈负责复杂的网络协议处理<br/>• 分层设计使每层专注自己的职责<br/>• 数据在各层间逐层封装<br/>• 操作系统屏蔽了底层网络复杂性
第 2 章:用电信号传输 TCP/IP 探索协议栈和网卡
TCP 三次握手
connect(<描述符>,<服务器IP地址和端口号>,…)
connect() 调用将服务器 IP 和端口传递给 TCP 模块,随后进行三次握手:
第一次握手:客户端创建 TCP 头部,设置 SYN=1 和端口号,通过 IP 模块发送给服务器。
第二次握手:服务器收到后找到对应套接字,状态改为正在连接,然后返回 SYN+ACK 响应,其中 ACK=1 表示确认收到客户端请求。
第三次握手:客户端收到响应后,向套接字写入服务器信息并改为连接完毕状态,最后发送 ACK=1 确认服务器响应。
服务器收到最终确认后,连接建立完成。
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#F0F4FC',
'primaryTextColor': '#1F2329',
'primaryBorderColor': '#000000',
'lineColor': '#888888',
'tertiaryColor': '#F5F6F7',
'tertiaryBorderColor': '#F5F6F7',
'tertiaryTextColor': '#00A4FF',
'noteBkgColor': '#FEF1CE',
'noteBorderColor': '#FEF1CE',
'noteTextColor': '#1F2329'
}
}
}%%
sequenceDiagram
participant C as 客户端<br/>(浏览器)<br/>状态: CLOSED
participant S as 服务器<br/>状态: LISTEN
Note over C,S: TCP 三次握手 - 建立可靠双向连接<br/>目标:确保双方都能正常发送和接收数据
Note over C: 为什么需要三次握手?<br/>1. 确认客户端发送能力<br/>2. 确认服务器收发能力<br/>3. 完成序列号同步<br/>4. 防止失效连接请求
rect rgb(255, 248, 240)
Note over C,S: 第一次握手 (SYN)
C->>S: SYN 标志位<br/>seq=x (初始序列号)<br/>"我想建立连接,我的序列号是 x"
Note right of S: 🔄 状态变化<br/>LISTEN → SYN_RCVD<br/><br/>✅ 确认:客户端能发送
end
rect rgb(240, 248, 255)
Note over C,S: 第二次握手 (SYN+ACK)
S->>C: SYN+ACK 标志位<br/>seq=y, ack=x+1<br/>"收到你的请求,我也想连接<br/>我的序列号是 y"
Note left of C: 🔄 状态变化<br/>SYN_SENT → ESTABLISHED<br/><br/>✅ 确认:服务器能收发
end
rect rgb(248, 255, 248)
Note over C,S: 第三次握手 (ACK)
C->>S: ACK 标志位<br/>seq=x+1, ack=y+1<br/>"收到确认,连接建立成功!"
Note right of S: 🔄 状态变化<br/>SYN_RCVD → ESTABLISHED<br/><br/>✅ 确认:客户端能接收<br/>序列号同步完成
end
Note over C,S: 连接建立成功!双向通信通道就绪<br/>序列号作用:保证数据顺序 | 防重复 | 可靠传输<br/>开始 HTTP 数据传输...
数据收发与连接断开
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#F0F4FC',
'primaryTextColor': '#1F2329',
'primaryBorderColor': '#000000',
'lineColor': '#888888',
'tertiaryColor': '#F5F6F7',
'tertiaryBorderColor': '#F5F6F7',
'tertiaryTextColor': '#00A4FF',
'noteBkgColor': '#FEF1CE',
'noteBorderColor': '#FEF1CE',
'noteTextColor': '#1F2329'
}
}
}%%
sequenceDiagram
participant C as 客户端
participant S as 服务器
Note over C,S: TCP 数据传输与连接关闭完整流程
rect rgb(255, 248, 240)
Note over C,S: 数据发送阶段
C->>S: 1. HTTP请求数据<br/>seq=1001, 数据1460字节
S->>C: 2. ACK确认<br/>ack=2461
C->>S: 3. 继续发送数据<br/>seq=2461, 数据1024字节
S->>C: 4. ACK确认<br/>ack=3485
end
rect rgb(240, 248, 255)
Note over C,S: 数据接收阶段
S->>C: 5. HTTP响应数据<br/>seq=5001, 数据1280字节
C->>S: 6. ACK确认<br/>ack=6281
S->>C: 7. 继续发送响应<br/>seq=6281, 数据1280字节
C->>S: 8. ACK确认<br/>ack=7561
Note over C,S: ... 继续传输直到完成
end
rect rgb(248, 255, 248)
Note over C,S: 四次挥手断开连接
C->>S: 9. FIN标志位<br/>seq=u<br/>"数据发送完毕,关闭连接"
S->>C: 10. ACK确认<br/>ack=u+1<br/>"收到关闭请求"
S->>C: 11. FIN标志位<br/>seq=v<br/>"我也要关闭连接"
C->>S: 12. ACK确认<br/>ack=v+1<br/>"连接彻底关闭"
end
Note over C,S: 关键机制:<br/>• 序列号确保数据顺序<br/>• ACK机制保证可靠传输<br/>• 四次挥手优雅关闭双向连接