当前位置: 首页 > article >正文

TCP/UDP传输过程

一、TCP消息发送全流程(以网页加载为例)


场景模拟
  • 客户端:IP地址 192.168.1.100,浏览器访问 http://www.example.com
  • 服务器:IP地址 93.184.216.34(www.example.com),监听端口 80

详细步骤

1. 建立连接:三次握手

  • 步骤 1:客户端发送 SYN 包(主动打开)

    [以太网帧] 目标MAC: 路由器MAC | 源MAC: 客户端MAC
    [IP头部] 源IP: 192.168.1.100 | 目标IP: 93.184.216.34 | TTL: 64
    [TCP头部]
      - 源端口: 54321(随机临时端口)
      - 目标端口: 80
      - 序列号(seq): 1000(随机初始值)
      - 标志位: SYN=1(请求建立连接)
      - 窗口大小: 65535(初始接收窗口)
    

    物理层行为:客户端网卡将数据包发送到默认网关(路由器)。

  • 步骤 2:服务器回复 SYN-ACK 包

    [TCP头部]
      - 源端口: 80
      - 目标端口: 54321
      - 序列号(seq): 5000(服务器初始序列号)
      - 确认号(ack): 1001(客户端seq+1)
      - 标志位: SYN=1, ACK=1
      - 窗口大小: 8192
    

    服务器行为

    • 检查目标端口 80 是否有进程监听(如Nginx)。
    • 创建新的 TCP 连接控制块(TCB),记录客户端IP和端口。
    • 分配缓冲区,准备接收数据。
  • 步骤 3:客户端发送 ACK 包(连接建立完成)

    [TCP头部]
      - 标志位: ACK=1
      - 序列号(seq): 1001(初始seq+1)
      - 确认号(ack): 5001(服务器seq+1)
    

    客户端行为

    • 进入 ESTABLISHED 状态,开始发送应用数据。
    • 若未收到 SYN-ACK,重试 SYN 包(默认最多重试5次)。

2. 数据传输:HTTP请求与响应

  • 步骤 4:客户端发送 HTTP GET 请求

    [TCP头部]
      - 序列号(seq): 1001
      - 确认号(ack): 5001
      - 标志位: ACK=1, PSH=1(推送数据)
    [HTTP数据] 
      GET /index.html HTTP/1.1
      Host: www.example.com
      User-Agent: Chrome/120.0
    

    数据分片规则

    • 假设数据总长度 500字节,MSS(最大分段大小)为 1460字节,无需分片。
    • 若数据超过 MSS,TCP 层会分片(如 seq=1001:2461seq=2461:3921)。
  • 步骤 5:服务器确认数据接收(ACK)

    [TCP头部]
      - 序列号(seq): 5001
      - 确认号(ack): 1001 + 500 = 1501
      - 标志位: ACK=1
    

    服务器行为

    • 将数据存入接收缓冲区,通知应用层(Nginx)读取。
    • 若客户端未收到 ACK,在超时(如 200ms)后重传数据。
  • 步骤 6:服务器发送 HTTP 响应

    [TCP头部]
      - 序列号(seq): 5001
      - 确认号(ack): 1501
      - 标志位: ACK=1, PSH=1
    [HTTP数据]
      HTTP/1.1 200 OK
      Content-Length: 1300
      <html>...</html>
    

    数据分片示例

    • 若响应数据 1300字节,分为两段发送:
      • 第一段:seq=5001:6461(长度1460字节)
      • 第二段:seq=6461:6561(剩余100字节)。
  • 步骤 7:客户端确认响应数据

    [TCP头部]
      - 序列号(seq): 1501
      - 确认号(ack): 5001 + 1300 = 6301
      - 标志位: ACK=1
    

    客户端行为

    • 将数据重组后传递给浏览器渲染。
    • 若服务器未收到 ACK,重传最后一个数据段。

3. 关闭连接:四次挥手

  • 步骤 8:客户端发送 FIN 包(主动关闭)

    [TCP头部]
      - 序列号(seq): 1501
      - 确认号(ack): 6301
      - 标志位: FIN=1, ACK=1
    

    客户端状态转换ESTABLISHEDFIN_WAIT_1

  • 步骤 9:服务器回复 ACK 包

    [TCP头部]
      - 序列号(seq): 6301
      - 确认号(ack): 1502(客户端seq+1)
      - 标志位: ACK=1
    

    服务器状态转换ESTABLISHEDCLOSE_WAIT

  • 步骤 10:服务器发送 FIN 包(被动关闭)

    [TCP头部]
      - 序列号(seq): 6301
      - 确认号(ack): 1502
      - 标志位: FIN=1, ACK=1
    

    服务器状态转换CLOSE_WAITLAST_ACK

  • 步骤 11:客户端回复 ACK 包

    [TCP头部]
      - 序列号(seq): 1502
      - 确认号(ack): 6302(服务器seq+1)
      - 标志位: ACK=1
    

    客户端状态转换FIN_WAIT_2TIME_WAIT(等待2MSL,如60秒后关闭)


二、UDP消息发送全流程(以DNS查询为例)


场景模拟
  • 客户端:IP 192.168.1.100,查询 www.google.com 的IP地址
  • DNS服务器:IP 8.8.8.8(Google Public DNS),端口 53

详细步骤

1. 构造DNS查询报文

  • 应用层:生成DNS查询请求

    [DNS报文]
      - Transaction ID: 0x3a8f
      - Flags: 递归查询(RD=1)
      - Questions: 1(查询www.google.com的A记录)
    
  • 传输层:封装为UDP数据报

    [UDP头部]
      - 源端口: 49152(客户端随机临时端口)
      - 目标端口: 53
      - 长度: 8(UDP头) + 40(DNS数据) = 48字节
      - 校验和: 0x2e45(计算覆盖伪头部+UDP头+数据)
    [数据部分] DNS查询报文(40字节)
    
  • 网络层:封装为IP数据包

    [IP头部]
      - 源IP: 192.168.1.100
      - 目标IP: 8.8.8.8
      - 协议字段: 17(UDP)
      - TTL: 64
    
  • 链路层:封装为以太网帧

    [以太网帧]
      - 目标MAC: 默认网关MAC(如路由器)
      - 源MAC: 客户端网卡MAC
      - 类型: 0x0800(IPv4)
    

2. 发送数据包(无连接建立)

  • 客户端行为

    • 直接发送UDP数据包到 8.8.8.8:53
    • 不等待任何确认,继续执行其他任务。
  • 网络传输过程

    • 路由器根据目标IP 8.8.8.8 查找路由表,通过ISP转发。
    • 若中间路由器拥塞,可能直接丢弃数据包(UDP无重传机制)。

3. DNS服务器处理请求

  • 服务器接收

    [校验和验证]
      - 计算伪头部(源IP、目标IP、协议、UDP长度)+ UDP头 + 数据。  
      - 若校验和错误,静默丢弃数据包。
    

    服务器行为

    • 解析DNS查询,查找 www.google.com 的A记录(如 142.250.189.196)。
    • 构造响应报文:
      [DNS响应]
        - Transaction ID: 0x3a8f(与请求匹配)
        - Flags: 响应(QR=1),递归可用(RA=1)
        - Answer: 1条A记录(142.250.189.196)
      
  • 服务器发送响应

    [UDP数据报]
      - 源端口: 53
      - 目标端口: 49152
      - 长度: 8 + 60 = 68字节
      - 校验和: 0x5d21
    [IP头部]
      - 源IP: 8.8.8.8
      - 目标IP: 192.168.1.100
    

4. 客户端接收响应(或超时处理)

  • 成功接收

    • 客户端校验和验证通过后,提取 142.250.189.196,完成DNS解析。
  • 丢包场景

    • 若响应包丢失,客户端等待超时(如 5秒)后重发查询。
    • 示例重传
      第1次发送: T=0s → 未收到响应  
      第2次发送: T=5s → 仍未响应  
      第3次发送: T=10s → 成功接收  
      

三、TCP与UDP对比的关键细节

动作TCPUDP
连接建立需要三次握手,消耗1.5 RTT无握手,直接发送
数据传输可靠性每个包必须确认,超时重传无确认,不保证到达
数据顺序接收端按序列号排序可能乱序到达
头部开销20字节(基础)+ 可选字段固定8字节
流量控制通过窗口大小动态调整无控制,依赖应用层
拥塞控制慢启动、拥塞避免、快速重传无,可能加剧网络拥塞

四、技术细节补充

  1. TCP的序列号与确认号

    • 序列号:标识数据段的第一个字节的编号(如 seq=1001 表示数据从第1001字节开始)。
    • 确认号:期望收到的下一个字节编号(如 ack=1501 表示已正确接收前1500字节)。
  2. UDP校验和计算

    • 伪头部:包含源IP、目标IP、协议号(17)、UDP长度,用于防止路由错误。
    • 计算示例
      # 伪头部 + UDP头 + 数据
      pseudo_header = src_ip + dst_ip + protocol + udp_length
      checksum_data = pseudo_header + udp_header + payload
      # 按16位字求和,取反码
      
  3. TCP状态机

    • 客户端典型状态流
      CLOSED → SYN_SENT → ESTABLISHED → FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT → CLOSED
    • 服务器典型状态流
      CLOSED → LISTEN → SYN_RCVD → ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED

五、实际抓包示例(Wireshark模拟)

TCP三次握手

No.  Time      Source           Destination      Protocol Info
1    0.000000 192.168.1.100    93.184.216.34    TCP      54321 → 80 [SYN] Seq=1000
2    0.102345 93.184.216.34    192.168.1.100    TCP      80 → 54321 [SYN, ACK] Seq=5000 Ack=1001
3    0.204678 192.168.1.100    93.184.216.34    TCP      54321 → 80 [ACK] Seq=1001 Ack=5001

UDP DNS查询

No.  Time      Source           Destination      Protocol Info
4    1.500000 192.168.1.100    8.8.8.8          UDP      49152 → 53 Len=48
5    1.602345 8.8.8.8          192.168.1.100    UDP      53 → 49152 Len=68

通过以上详细示例,可以清晰看到TCP如何通过握手、分段确认实现可靠传输,而UDP如何以极简方式实现快速通信。实际开发中需根据场景权衡选择协议。


http://www.kler.cn/a/594790.html

相关文章:

  • AI辅助的逆向分析
  • MutableList 和 ArrayList 区别
  • 画出ConcurrentHashMap 1.8的put流程图,记住CAS和synchronized的结合
  • 【Oracle资源损坏类故障】:详细了解坏块
  • 视觉Transformer架构的前沿优化技术与高效部署
  • 微服务》》Kubernetes (K8S) 集群配置网络》》Calico
  • Java 中 LinkedHashMap 的底层数据结构及相关分析
  • 甘特图dhtmlx-gantt 一行多任务
  • 【el-select 一键便捷全选】
  • 服务器托管如何抵御网络病毒?
  • AI小白的第七天:必要的数学知识(四)
  • Java面试核心知识点 深度拆解+高频易错
  • 设计模式之责任链模式:原理、实现与应用
  • 问题记录(一)——引入WebSocket依赖时的不兼容或冲突问题
  • 2025最新电脑IP地址修改方法:Win系统详细步骤
  • C++ - 从零实现Json-Rpc框架-1(JsonCpp Muduo 异步操作)
  • 四、小白学JAVA-石头剪刀布游戏
  • YZi Labs 谈对 Plume 的投资:利用区块链创造现实价值的典范项目
  • 【Linux】Makefile秘籍
  • 前端技巧:精准判断登录设备是移动端还是 PC 端