TCP/UDP传输过程

embedded/2025/3/22 10:44:06/

一、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/embedded/174666.html

相关文章

【Linux系统】进程等待:告别僵尸进程深入理解Linux进程同步的核心密码

Linux系列 文章目录 Linux系列前言一、进程等待的核心目的二、进程等待的实现方式2.1 wait()函数2.2 waitpid&#xff08;&#xff09;函数 总结 前言 在Linux系统中&#xff0c;进程等待&#xff08;Process Waiting&#xff09;是多进程编程中的核心机制&#xff0c;指父进程…

模型评估——acc、P、R、F值、交叉验证、K折交叉验证

模型评估&#xff1a;对预测函数地预测精度的评估。 多重回归&#xff1a;涉及三个及其以上的变量的回归问题。 评估模型的方法&#xff1a; 交叉验证&#xff1a;将数据集分成测试集和训练集&#xff0c;可以采用3&#xff1a;7或者2&#xff1a;8的比例方式进行划分&#xff…

参数估计学习笔记通俗易懂版(包括点估计和区间估计(区间估包括总体均值的置信区间(总体标准差未知、总体标准差已知)和总体方差的置信区间))

目录 1. 参数估计的基本概念2. 点估计2.2定义与特点2.3常见方法2.4点估计的应用 3. 区间估计3.1概念及意义3.2构造步骤3.3应用实例3.4区间估计题解 4. 贝叶斯估计中的区间估计5. 总结 1. 参数估计的基本概念 在统计推断中&#xff0c;我们往往希望利用从总体中抽取的有限样本来…

python爬虫笔记(一)

文章目录 html基础标签和下划线无序列表和有序列表表格加边框 html的属性a标签&#xff08;网站&#xff09;target属性换行线和水平分割线 图片设置宽高width&#xff0c;height html区块——块元素与行内元素块元素与行内元素块元素举例行内元素举例 表单from标签type属性pla…

【leetcode hot 100 22】括号生成

解法一&#xff1a;&#xff08;回溯法&#xff09;用两个整数记录左右括号数&#xff0c;以在回溯过程中保证先生成左括号&#xff0c;且左右括号数不能大于n。 class Solution {public List<String> generateParenthesis(int n) {List<String> result new Arra…

蓝桥杯————封闭图形个数(自定义排序问题)

20分钟&#xff0c;拿捏&#xff01;1.封闭图形个数 - 蓝桥云课 1.数位排序 - 蓝桥云课 思路和数位循环一样&#xff0c;其实 先初始化数组&#xff0c;包含两个数组&#xff0c;一个数组arr用来统计输入的数字 另一个数组num用来统计每个数的封闭图形的个数 static void in…

如何实现一个纯 CSS 的滑动门导航效果,需要用到哪些技术?

大白话如何实现一个纯 CSS 的滑动门导航效果&#xff0c;需要用到哪些技术&#xff1f; 什么是滑动门导航效果 滑动门导航效果是一种常见的网页导航设计&#xff0c;当你把鼠标悬停在导航菜单的某个选项上时&#xff0c;这个选项的背景会滑动或者变化&#xff0c;就好像门打开…

VSCode C/C++ 环境搭建指南

一、前言 Visual Studio Code&#xff08;简称 VSCode&#xff09;是一款轻量级且功能强大的跨平台代码编辑器&#xff0c;凭借丰富的插件生态和高度的可定制性&#xff0c;深受开发者喜爱。对于 C/C 开发者而言&#xff0c;在 VSCode 中搭建开发环境&#xff0c;能够获得灵活…