图解网络是怎样连接的

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 探索协议栈和网卡

picture-2025-06-20-09-53-51

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/>• 四次挥手优雅关闭双向连接