TCP/UDP传输过程

server/2025/3/31 21:50:19/

一、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.1Host: www.example.comUser-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 OKContent-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.ppmy.cn/server/176956.html

相关文章

ROS从小白到入门:知识点速通与面试指南

一、ROS核心概念 ROS是什么&#xff1f; ROS&#xff08;Robot Operating System&#xff09;是一个灵活的机器人软件框架&#xff0c;提供硬件抽象、通信机制、工具和库&#xff0c;帮助开发者快速构建机器人应用。 核心组件 节点&#xff08;Node&#xff09;&#xff1a;独…

turnjs图册翻书效果

npm install https://github.com/igghera/turn.js.git //或者 npm install turn.js //import $ from "jquery"; //记得引入jquery import turn.js; // 引入 Turn.jsimport turn from "/utils/turn.min.js";// 引入 Turn.jsinitBook(length) {var that thi…

UnitTest框架管理测试用例——python自动化测试

UnitTest框架 UnitTest是Python自带一个单元测试框架&#xff0c;常用它来做单元测试。 注意:对于测试来说&#xff0c;UnitTest框架的作用是 自动化脚本(用例代码)执行框架————(使用UnitTest框架来管理 运行多个测试用例的) 为什么使用UnitTest框架 能够组织多个用例去执…

头歌实训--数据预处理Pandas--共三关

第1关&#xff1a;合并数据 import pandas as pd import numpy as npdef data_merge():raw_data_1 {"subject_id": ["1", "2", "3", "4", "5"],"first_name": ["Alex", "Amy", &…

多包管理工具

一.bolt&#xff08;停止维护&#xff09; 公共库组件的特征之一就是代码复用率很高&#xff0c;改其中一部分代码&#xff0c;大部分组件就都需要更新一遍依赖&#xff0c;所以如何快速更新依赖、添加版本号、发布组件、上传组件代码就成了一个问题。这里我使用了bolt来批量管…

游戏引擎学习第171天

回顾并计划今天的内容 昨天&#xff0c;我们在处理一项任务时暂停了&#xff0c;当时的目标非常清晰&#xff0c;但由于时间限制&#xff0c;我们将其分成了两个部分。我们首先完成了运行时部分&#xff0c;而今天要处理的是资产打包部分。这项任务涉及改进字体系统&#xff0…

遨游科普:三防平板是哪三防?有哪些应用场景?

在工业智能化与数字化转型的浪潮中&#xff0c;电子设备的耐用性和环境适应性成为关键需求。普通消费级平板电脑虽然功能强大&#xff0c;但在极端环境下往往“水土不服”。而三防平板凭借其独特的防护性能&#xff0c;正逐步成为“危、急、特”场景的核心工具。 AORO P300 Ult…

shell 脚本搭建apache

#!/bin/bash # Set Apache version to install ## author: yuan# 检查外网连接 echo "检查外网连接..." ping www.baidu.com -c 3 > /dev/null 2>&1 if [ $? -eq 0 ]; thenecho "外网通讯良好&#xff01;" elseecho "网络连接失败&#x…