第9章:TFTP(Trivial File Transfer Protocol)
简单文件传输协议
一、导读
1.1 本章学习目标
第9章介绍TFTP(简单文件传输协议)——一个基于UDP的极简文件传输协议。TFTP设计简单、开销小,主要用于无盘工作站启动时下载引导程序,以及网络设备(路由器、交换机)的配置文件传输。虽然TFTP在通用文件传输领域已被FTP、SCP、SFTP等取代,但它在嵌入式和网络设备管理中仍有重要应用。
本章的核心学习目标包括:
- 理解TFTP的设计哲学:为什么在已有FTP的情况下还需要TFTP
- 掌握TFTP的报文格式:RRQ、WRQ、DATA、ACK、ERROR五种报文
- 深入理解停止-等待协议:TFTP如何使用简单的确认机制实现可靠传输
- 理解TFTP的超时重传机制:如何处理丢包和超时
- 掌握TFTP的传输模式:netascii、octet、mail三种模式的区别
- 了解TFTP的安全性和局限性:为什么TFTP不适合在公共网络使用
1.2 为什么本章如此重要
TFTP虽然简单,但它完美展示了网络协议设计中的一个重要原则:简单性。TFTP用最少的协议机制实现了基本的可靠文件传输,是学习停止-等待协议和可靠传输机制的绝佳案例。
此外,TFTP在网络工程中仍然广泛使用:
- 路由器/交换机从TFTP服务器加载固件和配置
- PXE网络启动使用TFTP下载引导程序
- VoIP电话从TFTP服务器获取配置文件
理解TFTP的工作原理,对于网络管理和嵌入式系统开发都有实际价值。
1.3 核心问题引导
在阅读本章时,请带着以下问题思考:
TFTP为什么选择UDP而不是TCP作为传输层协议?UDP的不可靠性如何在TFTP中弥补?
停止-等待协议的效率如何?在高速网络中,TFTP的传输速率受什么限制?
TFTP的数据块为什么是512字节?这个大小是如何确定的?
如果TFTP传输过程中丢失了一个ACK,会发生什么?丢失了一个DATA呢?
TFTP没有认证机制,如何防止未授权的文件访问?
TFTP的最后一个数据块为什么必须小于512字节?如果文件大小恰好是512的整数倍怎么办?
二、核心概念详解
2.1 TFTP的设计背景
TFTP(RFC 1350)设计于1992年,目标是提供一个极其简单的文件传输协议,能够在资源受限的环境中运行。
2.1.1 TFTP vs FTP
| 特性 | TFTP | FTP |
|---|---|---|
| 传输层 | UDP(端口69) | TCP(端口20/21) |
| 认证 | 无 | 用户名/密码 |
| 目录浏览 | 不支持 | 支持 |
| 文件传输模式 | 停止-等待 | 滑动窗口/流水线 |
| 代码大小 | 几KB | 几十KB |
| 适用场景 | 嵌入式、网络启动 | 通用文件传输 |
TFTP的设计目标:
- 代码量极小,可以嵌入到ROM中(无盘工作站)
- 支持简单的文件读写操作
- 不需要用户认证(简化实现)
- 使用UDP而非TCP(减少协议栈依赖)
2.2 TFTP的报文格式
TFTP有五种报文类型,每种都有2字节的操作码(opcode):
2.2.1 读请求(RRQ)和写请求(WRQ)
2 bytes string 1 byte string 1 byte
+--------+---------+------+---------+------+
| Opcode | Filename| 0 | Mode | 0 |
+--------+---------+------+---------+------+
opcode: 1=RRQ, 2=WRQ
filename: 文件名(ASCII字符串)
mode: "netascii" / "octet" / "mail"2.2.2 数据报文(DATA)
2 bytes 2 bytes n bytes
+--------+--------+----------+
| Opcode | Block# | Data |
+--------+--------+----------+
opcode: 3
block#: 块号(1-65535,循环)
data: 数据(最多512字节)2.2.3 确认报文(ACK)
2 bytes 2 bytes
+--------+--------+
| Opcode | Block# |
+--------+--------+
opcode: 4
block#: 确认的块号2.2.4 错误报文(ERROR)
2 bytes 2 bytes string 1 byte
+--------+--------+----------+------+
| Opcode | ErrCode| ErrMsg | 0 |
+--------+--------+----------+------+
opcode: 5
errcode: 错误代码(0-7)
errmsg: 错误描述2.3 停止-等待协议
TFTP使用停止-等待(stop-and-wait)协议实现可靠传输:发送一个数据块后,必须等待对方的ACK确认,才能发送下一个数据块。
2.3.1 文件读取流程
客户端 服务器
│ │
│ RRQ (filename, mode) │
│ (从随机端口 → 端口69) │
│ ────────────────────────────────→ │
│ │
│ 服务器分配新的TID(端口)
│ │
│ DATA (block=1, 512字节) │
│ (从服务器TID → 客户端TID) │
│ ←──────────────────────────────── │
│ │
│ ACK (block=1) │
│ ────────────────────────────────→ │
│ │
│ DATA (block=2, 512字节) │
│ ←──────────────────────────────── │
│ │
│ ACK (block=2) │
│ ────────────────────────────────→ │
│ │
│ ... │
│ │
│ DATA (block=N, <512字节) │
│ ←──────────────────────────────── │
│ │
│ ACK (block=N) │
│ ────────────────────────────────→ │
│ │
│ 传输完成 │2.3.2 关键规则
RRQ/WRQ发送到端口69,但后续DATA/ACK使用服务器分配的新端口(TID)
块号从1开始,每发送一个数据块递增1,超过65535后回到0
最后一个数据块小于512字节表示传输结束
ACK中的块号必须与DATA中的块号匹配
重复的ACK表示前一个DATA丢失,需要重传
2.4 超时重传
TFTP使用简单的超时重传机制:
发送DATA → 启动定时器(5秒)
→ 收到ACK → 停止定时器,发送下一个DATA
→ 定时器超时 → 重传DATA,重启定时器
→ 重试次数达到上限 → 报错退出默认超时时间为5秒,最大重试次数通常为3-5次。
2.4.1 超时重传的场景
| 场景 | 处理 |
|---|---|
| DATA丢失 | 发送方超时重传DATA |
| ACK丢失 | 发送方超时重传DATA,接收方收到重复DATA后重发ACK |
| RRQ丢失 | 客户端超时重传RRQ |
2.5 传输模式
| 模式 | 说明 |
|---|---|
| netascii | 文本模式,进行换行符转换(LF↔CRLF) |
| octet | 二进制模式(也称"stream"),原样传输 |
| 邮件模式,通过邮件发送文件(很少使用) |
现代使用几乎都采用octet模式。
2.6 TFTP的安全性和局限性
2.6.1 安全问题
- 无认证:任何人都可以读写文件
- 无加密:数据明文传输
- 无访问控制:通常只能限制访问的目录
2.6.2 性能限制
- 停止-等待协议效率低:每个数据块都需要等待ACK,RTT成为瓶颈
- 数据块小:512字节/块,头部开销大
- 无流水线:不能同时传输多个数据块
2.6.3 TFTP的扩展
RFC 2347/2348/2349定义了TFTP选项扩展:
- blksize:增大数据块大小(如1468字节)
- timeout:自定义超时时间
- tsize:传输前告知文件大小
三、实战案例
3.1 案例一:使用tcpdump观察TFTP传输
# 在服务器端抓包
sudo tcpdump -i eth0 -nn 'udp port 69 or udp portrange 32768-65535'输出示例:
# 客户端发送RRQ
12:34:56.789 IP 192.168.1.100.50000 > 192.168.1.1.69:
34 bytes: RRQ "config.txt" octet
# 服务器响应DATA(从新端口)
12:34:56.790 IP 192.168.1.1.40000 > 192.168.1.100.50000:
516 bytes: DATA block=1
# 客户端ACK
12:34:56.791 IP 192.168.1.100.50000 > 192.168.1.1.40000:
4 bytes: ACK block=1
# 服务器DATA
12:34:56.792 IP 192.168.1.1.40000 > 192.168.1.100.50000:
516 bytes: DATA block=23.2 案例二:使用tftp客户端
# 连接TFTP服务器
tftp 192.168.1.1
# 下载文件
tftp> get config.txt
# 上传文件
tftp> put local.txt
# 二进制模式
tftp> mode octet
# 退出
tftp> quit3.3 案例三:搭建TFTP服务器
# 安装tftp-hpa
sudo apt install tftp-hpa tftpd-hpa
# 配置 /etc/default/tftpd-hpa
# TFTP_DIRECTORY="/var/lib/tftpboot"
# TFTP_ADDRESS=":69"
# TFTP_OPTIONS="--secure"
# 启动服务
sudo systemctl start tftpd-hpa
# 放置文件
sudo cp firmware.bin /var/lib/tftpboot/四、常见误区与难点
4.1 误区一:"TFTP使用TCP"
TFTP使用UDP。它的可靠性完全在应用层通过停止-等待协议实现。
4.2 误区二:"TFTP的端口始终是69"
端口69只用于初始的RRQ/WRQ请求。服务器收到请求后,会分配一个新的临时端口(TID)进行后续的数据传输。
4.3 难点:理解块号的循环
块号是16位,范围0-65535。对于大于32MB的文件(65536×512字节),块号会回到0。TFTP实现需要正确处理这种情况。
五、本章小结
第9章介绍了TFTP协议:
TFTP基于UDP,使用停止-等待协议实现可靠传输,设计极其简单。
五种报文:RRQ、WRQ、DATA、ACK、ERROR,各有固定格式。
停止-等待协议:发送一个数据块后等待ACK,效率受RTT限制。
数据块512字节,最后一个块小于512字节表示传输结束。
无认证和加密,仅适用于受控环境(内网、设备管理)。
六、思考与练习
思考题
TFTP的停止-等待协议在RTT=100ms的网络中,最大传输速率是多少?如何改进?
如果TFTP传输过程中,服务器崩溃了,客户端如何检测到?
为什么TFTP的RRQ/WRQ发送到端口69,而后续数据传输使用新端口?
练习题
搭建TFTP服务器,使用tcpdump观察完整的文件传输过程,分析每个报文的字段。
编写一个简单的TFTP客户端程序,实现文件下载功能。
测试TFTP在不同丢包率下的传输性能,分析超时重传的行为。