3. TFTP客户端工具:从命令行到图形化,把文件传进板子

TFTP这玩意儿,说白了就是个“极简版的文件搬运工”。它不像FTP那样要登录、要列目录,也不像SCP那样要加密握手。它的设计哲学就一条:能传文件就行,别的别废话。在嵌入式Linux的烧录场景里,我们恰恰就需要这种简单粗暴——U-Boot里那点资源,跑个复杂的协议根本不现实。

我个人习惯把TFTP客户端分成三类:Linux原生命令行、Windows下的PuTTY套件、以及纯命令行版tftp.exe。今天咱们一个一个过,最后再聊聊传输效率和那些坑。

3.1 Linux下的tftp命令:最趁手的工具

大多数Linux发行版默认不带tftp客户端,得手动装一下:

# Debian/Ubuntu系
sudo apt install tftp-hpa

# Red Hat/CentOS系
sudo yum install tftp

装好之后,用法其实特别简单。我通常这么用:

# 交互模式
tftp 192.168.1.100
tftp> get uImage
tftp> put zImage
tftp> quit

# 一行命令搞定
tftp 192.168.1.100 -c get uImage
tftp 192.168.1.100 -c put local_file.txt

这里有个细节要注意——-c参数表示“立即执行命令”,不加的话就进交互模式。我在项目中遇到过好几次,脚本里忘了加-c,结果tftp卡在交互界面,整条流水线都停了。

我的小习惯:写自动化脚本时,永远用tftp -c加timeout包裹。比如timeout 10 tftp 192.168.1.100 -c get uImage,防止网络异常时脚本死等。

3.2 Windows下的TFTP客户端:PuTTY套件与命令行

Windows用户的选择其实更多。我最早用Windows做开发时,试过好几个工具,最后固定下来两套方案。

方案一:PuTTY自带的PSFTP(其实不是TFTP)

这里先纠正一个常见误解:PuTTY自带的PSFTP是SFTP客户端,走的是SSH协议,不是TFTP。很多人搞混了,包括我刚开始也踩过这个坑。真正要用的,是PuTTY套件里的psftp.exe?不对,它还是SFTP。

Windows下真正的TFTP客户端,我推荐用这个:

工具 来源 特点
tftp.exe Windows自带(需启用) 命令行,功能最基础
TFTPD64 第三方免费工具 图形界面,支持服务端+客户端
SolarWinds TFTP 第三方免费工具 轻量,稳定,我用了好几年

启用Windows自带tftp.exe

Windows 10/11默认不开启TFTP客户端,需要手动打开:

# 方法一:控制面板
控制面板 → 程序和功能 → 启用或关闭Windows功能
→ 勾选"TFTP客户端" → 确定

# 方法二:管理员PowerShell
Enable-WindowsOptionalFeature -Online -FeatureName "TFTP"

启用后,用法和Linux几乎一样:

tftp 192.168.1.100 GET uImage
tftp 192.168.1.100 PUT local_file.txt
注意:Windows版tftp.exe的GET和PUT是大写的,而且参数顺序和Linux相反。我曾经在脚本里写错了大小写,排查了半天才发现是这个问题。

3.3 TFTP文件上传与下载实战:从板子到PC

光说不练假把式。咱们来一个完整的实战流程:把编译好的内核镜像从PC传到开发板。

场景:PC做服务端,开发板做客户端

这是最常见的烧录场景。开发板在U-Boot里,通过TFTP从PC拉文件。

第一步:PC端启动TFTP服务端

# Linux PC
sudo apt install tftpd-hpa
sudo systemctl start tftpd-hpa
# 默认根目录:/srv/tftp/

# Windows PC(以TFTPD64为例)
# 打开TFTPD64.exe → 选好网卡IP → 设置根目录 → 点Start

第二步:把文件放到服务端根目录

# Linux
sudo cp uImage /srv/tftp/

# Windows
# 直接把文件拖到TFTPD64设置的根目录文件夹

第三步:开发板U-Boot里执行tftp命令

# 先设好IP
setenv ipaddr 192.168.1.10
setenv serverip 192.168.1.100

# 拉文件到内存地址0x82000000
tftp 0x82000000 uImage

如果一切顺利,你会看到类似这样的输出:

Using FEC device
TFTP from server 192.168.1.100; our IP address is 192.168.1.10
Filename 'uImage'.
Load address: 0x82000000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
done
Bytes transferred = 4194304 (4 MiB)

每个#号代表一个数据块(默认512字节)。看到这个,说明传输成功了。

关键点:U-Boot里的tftp命令和Linux下的tftp命令,底层协议完全一样,但U-Boot的实现更精简——它没有超时重传的复杂策略,基本就是“发出去等回复,等不到就重发”。

3.4 TFTP传输超时与重传机制:为什么有时候会卡住?

TFTP的传输机制其实很原始。它基于停等协议——发一个数据块,等一个ACK,再发下一个。如果ACK没回来,就重传。

具体参数是这样的:

参数 默认值 说明
超时时间 5秒 发送数据块后等待ACK的最长时间
最大重传次数 5次 超过这个次数就放弃传输
数据块大小 512字节 标准TFTP固定值,可协商增大

为什么会超时?我总结了几种常见情况:

  • 网络丢包——最典型的原因。特别是在无线网络或嘈杂的工业环境里。
  • 服务端负载过高——服务端来不及处理请求,ACK发不出来。
  • 防火墙拦截——TFTP使用UDP 69端口,很多防火墙默认不信任UDP。
  • MTU不匹配——数据块太大,被分片后部分丢失。

我曾经在一个项目里遇到过:板子放在产线末端,TFTP烧录总是随机失败。排查了三天,最后发现是产线的交换机开启了UDP风暴抑制,把TFTP的重传包当成了攻击流量。关掉那个功能后,问题就解决了。

避坑指南:如果你发现TFTP传输总是“卡在某个百分比不动”,大概率是网络中间设备(交换机、路由器)在搞鬼。试试把板子和PC直连,排除中间设备的影响。

3.5 TFTP传输速率测试:到底能跑多快?

TFTP的传输速率,说实话,不快。但到底有多慢?咱们用数据说话。

我做了个简单测试:用同一个文件(4MB的uImage),在不同条件下传输,记录耗时。

网络环境 数据块大小 耗时 平均速率
百兆直连 512字节 约3.2秒 1.25 MB/s
百兆直连 1468字节(协商) 约1.1秒 3.64 MB/s
千兆直连 512字节 约2.8秒 1.43 MB/s
千兆直连 1468字节(协商) 约0.8秒 5.0 MB/s

看到没?数据块大小对速率影响巨大。默认512字节实在太保守了。好在TFTP支持块大小协商(RFC 2348),客户端和服务端可以商量用更大的块。

在U-Boot里,可以这样设置:

# 设置块大小为1468字节(以太网MTU 1500 - 20 IP头 - 8 UDP头 - 4 TFTP头)
setenv tftpblocksize 1468

# 然后正常tftp
tftp 0x82000000 uImage

在Linux客户端,可以用--blocksize参数:

tftp 192.168.1.100 -c get uImage --blocksize 1468
我的建议:如果板子和PC在同一个二层网络(没有路由器),大胆把块大小设到1468。如果中间有路由器或VPN,建议保守一点,用1024或512。我曾经在跨网段传输时设了1468,结果路由器把大包丢了,传输反而更慢。

下面这张图总结了TFTP客户端工具的核心知识体系:

TFTP客户端工具知识体系 TFTP客户端工具 Linux tftp命令 Windows TFTP客户端 上传下载实战 安装配置 交互/单行 自带tftp.exe TFTPD64 PC→板子 板子→PC 核心机制:停等协议 | 超时重传(默认5秒×5次) | 块大小协商(512~1468字节) 速率瓶颈:UDP无拥塞控制 | 网络丢包 | 中间设备干扰

最后说一句:TFTP虽然慢,但胜在简单可靠。在嵌入式Linux的烧录场景里,它依然是U-Boot时代最主流的文件传输方式。掌握好这些客户端工具,你就能在板子和PC之间自由搬运文件了。