TCP/IP协议和TFTP协议

一、TCP 报文段结构

复制代码
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          源端口号(16bit)        |         目的端口号(16bit)      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        序列号 Seq (32bit)                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        确认号 Ack (32bit)                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 首部长度(4) |  保留(6)  |U|A|P|R|S|F|      窗口大小(16bit)      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           校验和(16bit)         |         紧急指针(16bit)       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    选项字段(最多40字节)                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          数 据                                  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

各字段详解:

字段 大小 说明
源/目的端口号 各16bit 标识发送/接收方的应用程序
序列号(Seq) 32bit 本报文段第一个字节的序号,用于数据排序和重传
确认号(Ack) 32bit 期望收到的下一个字节序号(Ack=N 表示 N-1 之前全部收到)
首部长度 4bit TCP 头部长度(单位:4字节),最小20字节,最大60字节
URG 1bit 紧急位,URG=1 时紧急指针有效
ACK 1bit 确认位,ACK=1 时确认号字段有效(握手后所有报文 ACK=1)
PSH 1bit 推送位,接收方应尽快将数据交给应用层
RST 1bit 复位位,RST=1 表示连接出现严重错误,需重新建立
SYN 1bit 同步位,SYN=1 用于建立连接(三次握手)
FIN 1bit 终止位,FIN=1 表示发送方数据发完,请求释放连接
窗口大小 16bit 接收方告知发送方自己的接收缓冲区剩余空间(流量控制核心)
校验和 16bit 覆盖整个 TCP 报文段(含伪首部)的校验
紧急指针 16bit 指出紧急数据的末尾位置(URG=1 时有效)

二、TCP 三次握手详解

2.1 握手过程

复制代码
客户端(CLOSED)                     服务端(LISTEN)
      │                                    │
      │────── SYN=1, Seq=x ──────────────→│  服务端:SYN_RCVD
      │        第一次握手                   │
      │                                    │
      │←──── SYN=1, ACK=1, Seq=y, Ack=x+1│  客户端:ESTABLISHED
      │        第二次握手                   │
      │                                    │
      │────── ACK=1, Seq=x+1, Ack=y+1 ───→│  服务端:ESTABLISHED
      │        第三次握手                   │
      │                                    │

三次握手各阶段说明:

次数 发送方 关键标志位 含义
第一次 客户端 → 服务端 SYN=1, Seq=x 客户端请求建立连接,发送初始序列号 x
第二次 服务端 → 客户端 SYN=1, ACK=1, Seq=y, Ack=x+1 服务端同意连接,并发送自己的初始序列号 y,确认已收到 x
第三次 客户端 → 服务端 ACK=1, Seq=x+1, Ack=y+1 客户端确认服务端的序列号 y

2.2 为什么是三次而不是两次?

两次握手无法确认"客户端能接收服务端数据"这一能力

三次握手验证目标 说明
客户端发送能力 第一次握手(服务端收到 SYN)✅
服务端接收能力 第一次握手(服务端收到 SYN)✅
服务端发送能力 第二次握手(客户端收到 SYN-ACK)✅
客户端接收能力 第二次握手(客户端收到 SYN-ACK)✅
客户端确认服务端序列号 第三次握手才能验证

三、TCP 四次挥手详解

3.1 挥手过程

复制代码
主动关闭方(A)                      被动关闭方(B)
      │                                    │
      │────── FIN=1, Seq=u ──────────────→│  B:CLOSE_WAIT
      │        第一次挥手(A不再发数据)     │
      │                                    │
      │←───── ACK=1, Ack=u+1 ─────────────│  A:FIN_WAIT_2
      │        第二次挥手(B确认,可能继续发数据)
      │                                    │
      │        B 处理完剩余数据...           │
      │                                    │
      │←───── FIN=1, ACK=1, Seq=v ────────│  B:LAST_ACK
      │        第三次挥手(B也不再发数据)   │
      │                                    │
      │────── ACK=1, Ack=v+1 ────────────→│  B:CLOSED
      │        第四次挥手                   │
      │(A 等待 2MSL 后进入 CLOSED)        │

3.2 TIME_WAIT 状态

属性 说明
出现位置 主动关闭方(A)在发送最后一个 ACK 后进入 TIME_WAIT
等待时间 2MSL(MSL = 最大报文生存时间,一般 60秒,故等待 120秒)
为什么等 1. 确保最后的 ACK 送达对端 (若丢失,B 会重发 FIN,A 可重发 ACK)2. 让本连接所有报文在网络中自然消亡,避免影响下一个同端口连接
实际影响 服务端重启后端口处于 TIME_WAIT 无法立即绑定 → 用 SO_REUSEADDR 解决

3.3 为什么挥手需要四次?

TCP 是全双工的,每个方向的数据流独立关闭。 A 说"我说完了",B 回答"好的",但 B 可能还有数据要发,等 B 也说完后再发 FIN,A 最后确认。第二次和第三次挥手不能合并(B 可能需要时间发完剩余数据)


四、TCP 状态机

4.1 TCP 完整状态转换

状态 说明 出现在
CLOSED 初始/关闭状态 两端
LISTEN 监听中,等待连接请求 服务端(bind+listen后)
SYN_SENT 已发送 SYN,等待对方确认 客户端(connect后)
SYN_RCVD 已收到 SYN 并回复 SYN-ACK 服务端(收到第一次握手后)
ESTABLISHED 连接已建立,可以通信 两端(握手完成后)
FIN_WAIT_1 已发送 FIN,等待对方确认 主动关闭方
FIN_WAIT_2 收到对方 ACK,等待对方 FIN 主动关闭方
TIME_WAIT 等待 2MSL,确保对方收到 ACK 主动关闭方(最后阶段)
CLOSE_WAIT 收到 FIN,等待应用层关闭 被动关闭方
LAST_ACK 已发 FIN,等待最后的 ACK 被动关闭方
CLOSING 双方同时关闭(极少见) 两端

📌 netstat -an 可查看当前系统所有 TCP 连接状态


五、TCP 可靠传输机制

5.1 确认与重传

机制 说明
累积确认 Ack=N 表示 N 之前的所有数据已收到,不对每个包单独确认
超时重传 发送方启动定时器,超时未收到 ACK 则重发(RTO 动态计算
快速重传 收到 3 个重复 ACK 时立即重传,无需等待超时

5.2 流量控制 ------ 滑动窗口

复制代码
发送方                              接收方
  │                                   │
  │  发送窗口大小 = 接收方通告的窗口   │
  │                                   │
  已确认 | 已发待确认 | 可发未发 | 不可发
  ←─────────── 发送窗口 ───────────→

接收方缓冲区满 → 通告窗口=0 → 发送方停发 → 零窗口探测
  • 核心:发送方不能发超过接收方缓冲区剩余空间的数据
  • 窗口大小 字段(16bit)= 接收方当前可用缓冲区大小

5.3 拥塞控制

阶段 算法 说明
慢开始 指数增长 拥塞窗口从1开始,每个 RTT 翻倍
拥塞避免 线性增长 窗口超过阈值(ssthresh)后,每个 RTT +1
快速重传 立即重传 收到3个重复ACK,不等超时
快速恢复 减半恢复 快速重传后,ssthresh减半,从新ssthresh开始线性增长

六、IP 协议与路由

6.1 IP 协议核心特性

特性 说明
无连接 每个数据包独立路由,不需预先建立路径
不可靠 尽力而为投递,不保证到达、顺序、不重复
分片与重组 数据包超过链路 MTU 时分片,目的端重组
TTL 生存时间 每经过一个路由器 TTL-1,TTL=0 时丢弃并回 ICMP Time Exceeded

6.2 路由选择

复制代码
数据包到达路由器后的查表步骤:

1. 用目的 IP 与每条路由的子网掩码做 AND 运算
2. 结果与路由表中的网络地址比较
3. 找到匹配的路由 → 转发到对应接口/下一跳
4. 没有匹配 → 转发到默认路由(0.0.0.0/0)
5. 连默认路由都没有 → 丢弃,回 ICMP Destination Unreachable

6.3 ICMP 协议

ICMP 报文类型 Type/Code 说明 触发场景
Echo Request/Reply 8/0 和 0/0 ping 命令使用 检测网络连通性
Destination Unreachable 3/x 目标不可达 端口未开放、路由不存在
Time Exceeded 11/0 TTL 超时 traceroute 使用此原理
Redirect 5/x 路由重定向 通知主机更优路由

七、ARP 协议详解

7.1 ARP 工作原理

ARP(Address Resolution Protocol):在已知 IP 地址的情况下,获取对应的 MAC 地址

复制代码
主机A(知道目标IP,不知道目标MAC)
  │
  ├── 查 ARP 缓存表(arp -a 查看)
  │       │
  │    命中 ──→ 直接使用缓存的 MAC
  │       │
  │    未命中
  │       │
  │    发 ARP 广播请求
  │    "谁的 IP 是 192.168.1.2?把你的 MAC 告诉我"
  │    目的 MAC = FF:FF:FF:FF:FF:FF(广播)
  │       │
  │  目标主机B 单播回复
  │    "我是 192.168.1.2,我的 MAC 是 00:1A:2B:3C:4D:5E"
  │       │
  │  主机A 更新 ARP 缓存,完成通信

7.2 ARP 报文格式

字段 大小 说明
硬件类型 2字节 以太网 = 1
协议类型 2字节 IPv4 = 0x0800
硬件地址长度 1字节 MAC 地址 = 6
协议地址长度 1字节 IPv4 = 4
操作码 2字节 1=ARP请求,2=ARP回复;3=RARP请求,4=RARP回复
发送方 MAC 6字节 发送者的硬件地址
发送方 IP 4字节 发送者的 IP 地址
目标 MAC 6字节 ARP 请求时全为0(未知)
目标 IP 4字节 要查询的目标 IP 地址

八、TFTP 协议概述

8.1 什么是 TFTP?

属性 内容
全称 Trivial File Transfer Protocol(简单文件传输协议)
传输层 基于 UDP (端口 69
特点 简单轻量,无需认证,无目录浏览功能
RFC RFC 1350
应用场景 网络设备固件升级、PXE 无盘启动、嵌入式系统引导

8.2 TFTP vs FTP 对比

对比项 TFTP FTP
传输层协议 UDP(端口 69) TCP(端口 21/20)
认证 无认证 用户名+密码
目录操作 不支持 支持(ls/cd 等)
可靠性 自实现 stop-and-wait ARQ 依赖 TCP
文件大小 理论上不限(实际受 ACK 号限制,原始版本 ≤32MB) 无限制
适用场景 网络启动、固件升级、嵌入式 通用文件传输

九、TFTP 报文格式

9.1 操作码(OpCode)

OpCode 报文类型 方向
RRQ 1 读请求(Read Request) 客户端 → 服务端
WRQ 2 写请求(Write Request) 客户端 → 服务端
DATA 3 数据报文 服务端↔客户端
ACK 4 确认报文 服务端↔客户端
ERROR 5 错误报文 服务端↔客户端

9.2 各类报文格式

① RRQ / WRQ 请求报文
复制代码
+--------+----------+---+----------+---+
| OpCode | Filename | 0 |   Mode   | 0 |
| 2字节  |  字符串  | 1 |  字符串  | 1 |
+--------+----------+---+----------+---+
字段 说明
OpCode 1=RRQ(读),2=WRQ(写)
Filename 文件名(以 \0 结尾的字符串)
Mode 传输模式:"octet"(二进制,最常用)或 "netascii"(文本)

② DATA 数据报文
复制代码
+--------+---------+---------+
| OpCode |  Block# |  Data   |
|  0x03  |  2字节  | 1~512字节|
+--------+---------+---------+
字段 说明
OpCode 3
Block# 块编号,从 1 开始,每次 +1,用于丢包重传和去重
Data 数据内容,固定大小 512 字节若小于 512 字节,表示是最后一块(传输结束标志)

⚠️ 判断文件传输结束:收到 Data 数据长度 < 512 字节(或为 0),说明是最后一块


③ ACK 确认报文
复制代码
+--------+---------+
| OpCode |  Block# |
|  0x04  |  2字节  |
+--------+---------+
字段 说明
OpCode 4
Block# 与对应 DATA 报文的 Block# 一致;WRQ 请求的确认 ACK 中 Block#=0

④ ERROR 错误报文
复制代码
+--------+----------+-----------+---+
| OpCode | ErrorCode | ErrMsg    | 0 |
|  0x05  |  2字节   |  字符串   | 1 |
+--------+----------+-----------+---+

错误码含义:

ErrorCode 含义
0 未定义错误
1 文件未找到(File not found)
2 访问违规(Access violation)
3 磁盘满或超出分配空间
4 非法操作
5 未知的传输 ID
6 文件已存在(File already exists)
7 无此用户

十、TFTP 传输流程

10.1 读文件流程(RRQ)

复制代码
客户端(随机端口)              服务端(初始 69 端口)
       │                                │
       │──── RRQ(文件名、模式)────────→│ 端口 69
       │                                │(服务端换随机端口 TID)
       │←─── DATA Block#1(512字节)────│ 随机端口 TID
       │──── ACK  Block#1 ─────────────→│
       │                                │
       │←─── DATA Block#2(512字节)────│
       │──── ACK  Block#2 ─────────────→│
       │                                │
       │←─── DATA Block#n(< 512字节)──│  ← 最后一块(标志结束)
       │──── ACK  Block#n ─────────────→│
       │                                │  传输完成

⚠️ 服务端收到 RRQ 后,会换一个随机端口(TID,Transfer Identifier)与客户端通信,不再使用 69 端口!


10.2 写文件流程(WRQ)

复制代码
客户端(随机端口)              服务端(初始 69 端口)
       │                                │
       │──── WRQ(文件名、模式)────────→│ 端口 69
       │                                │
       │←─── ACK Block#0 ──────────────│ 随机端口 TID(Block#0 表示可以发送)
       │──── DATA Block#1(512字节)────→│
       │←─── ACK  Block#1 ─────────────│
       │                                │
       │──── DATA Block#n(< 512字节)──→│  ← 最后一块
       │←─── ACK  Block#n ─────────────│
       │                                │  传输完成

10.3 超时与重传机制

TFTP 基于 stop-and-wait ARQ(停止等待协议),每次只发一个块,收到 ACK 再发下一块

机制 说明
超时重传 发送方等待 ACK,超时(通常 5 秒)未收到则重传上一个数据包
去重 接收方通过 Block# 检测重复包,重复 DATA 则重发对应 ACK,但不重复处理
Sorcerer's Apprentice Bug 若 ACK 延迟导致发送方重传,接收方回 ACK,触发级联重传 → 现代实现对最后一个 ACK 加延迟解决

十一、TFTP 编程实现

11.1 TFTP 客户端下载文件(读请求)

c

复制

编译: gcc -o tftp_client tftp_client.c 运行: ./tftp_client 192.168.1.100 test.txt ./test.txt


11.2 关键报文构造速查

c

复制


十二、总结速记卡

知识点 核心记忆
TCP 报文头 最小 20 字节;SYN/ACK/FIN/RST 是最重要的标志位
三次握手 SYN → SYN+ACK → ACK;验证双方收发能力
四次挥手 FIN → ACK → FIN → ACK;全双工各自独立关闭
TIME_WAIT 主动关闭方等待 2MSL(约120秒)SO_REUSEADDR 解决端口占用
Ack 确认号 Ack=N 表示 N-1 之前全部收到,期望收到 N
窗口控制 窗口=0 → 停止发送 → 零窗口探测
拥塞控制 慢开始(指数)→ 拥塞避免(线性)→ 快重传+快恢复
TTL 每过一个路由器 -1,=0 丢弃并返回 ICMP 超时
ARP IP→MAC;广播请求,单播回复;有缓存表
TFTP 端口 服务端初始监听 69/UDP;收到请求后换随机端口(TID)通信
TFTP 操作码 1=RRQ, 2=WRQ, 3=DATA, 4=ACK, 5=ERROR
TFTP 块大小 数据块固定 512 字节,最后一块 < 512(结束标志)
TFTP 可靠性 stop-and-wait ARQ:发一块→等ACK→发下一块
TFTP vs FTP TFTP=UDP+无认证+简单;FTP=TCP+认证+目录操作
相关推荐
Rudon滨海渔村1 小时前
macOS启动转换助理出现“不能下载该软件,因为网络出现问题 ”
网络·macos
xiaoxue..1 小时前
HTTPS:更安全的HTTP,从加密原理、数字证书到TLS 握手全解析
网络协议·面试·https
我爱C编程2 小时前
基于Sarsa强化学习的异构蜂窝网络中基站休眠算法matlab仿真
网络·matlab·强化学习·sarsa·异构蜂窝网络·基站休眠
大明者省2 小时前
手机访问虚拟机里面的网站(从虚拟机桥接网络到宝塔面板可访问)
linux·服务器·网络
fiveym2 小时前
BIOS/UEFI模式PXE装机全解析
服务器·网络·性能优化
剑神一笑2 小时前
Linux netstat 命令深度解析:从网络连接到端口监控的完整实现
linux·运维·网络
99乘法口诀万物皆可变2 小时前
UDS诊断测试用例评审方法论:以BMS产品为例的六大维度与改进路线图
网络·测试用例
liulilittle2 小时前
TCP UCP v1.0 拥塞控制算法(Linux Kernel CC-A)
linux·网络·网络协议·tcp/ip·c·通信·拥塞控制
emm的金毛2 小时前
PCIe总线-PCIe体系结构(3)
网络·pcie