前言
主要是想看看常见的服务器和客户端是如何实现协议中要求的功能的,。
比如RF959要求的记录结构(Record Structure)、页结构(Page Structure)、Block Mode、Compress Mode,看起来就很抽象。
实测发现,那些很抽象的要求,常见的服务器和客户端都没实现。(很好,我也有理由不实现了🥰)
服务器
一、vsftpd
官网标题Probably the most secure and fastest FTP server for UNIX-like systems,可见它非常靠谱。
二、FileZilla Server
- 待办
客户端
一、Windows自带的FTP客户端
优点: 无
缺点:
- 支持的命令非常少,非常难用!!!
- 传输/下载没有进度条提示,不知道要等多久,传输大文件时,不知道的还以为卡住了!!!
- 控制台中文乱码(属于是控制台原因了)!!!
- 只支持PORT模式,不支持PASV模式,这个非常重要!!!
- 闭源!!!
总之就是一坨,可能还没我自己写的好用。
二、linux自带的tnftp客户端
Linux自带的ftp是tnftp。
在我的debian12上,这个软件包的信息如下:
Package: tnftp
Version: 20210827-4+b1
Priority: optional
Section: net
Source: tnftp (20210827-4)
Maintainer: xiao sheng wen <atzlinux@sina.com>
Installed-Size: 263 kB
Provides: ftp
Depends: libc6 (>= 2.33), libedit2 (>= 2.11-20080614-0), libssl3 (>= 3.0.0)
Conflicts: lukemftp
Replaces: lukemftp
Homepage: http://en.wikipedia.org/wiki/Tnftp
Tag: network::client, protocol::ftp, role::program, uitoolkit::ncurses,
use::downloading, works-with::file
Download-Size: 128 kB
APT-Manual-Installed: no
APT-Sources: https://mirrors.tuna.tsinghua.edu.cn/debian bookworm/main amd64 Packages
Description: 增强 ftp 客户端
tnftp 在 NetBSD (http://www.netbsd.org) 里,许多用户亲切的称呼为增强 ftp 客户
端。
.
该软件包是 NetBSD ftp 客户端到其它系统的移植。
.
相比于 4.4BSD 里的标准 ftp 客户端,tnftp 实现了如下增强:
* 在 ftp 里面的命令行编辑
* 命令行获取网址,包括支持:
- http 代理(参见:$http_proxy, $ftp_proxy)
- 认证
* 上下文敏感的命令和文件名补齐
* 动态进度显示
* IPv6 支持(来自 WIDE 项目)
* 修改时间保留
* 按页显示本地和远程文件,列出的目录(参见:`lpage', `page', `pdir')
* 被动模式支持,并能返回到主动模式
* `set option 设置选项' 忽略 ftp 环境变量
* TIS 防火墙工具包网关 ftp 代理支持(参见:`gate')
* 传输速度限流(参见:`-T', `rate')
它的命令很多,比widnows的丰富,但是,
在实现FTP服务器和客户端时,也发现了一些它的一些问题。
1. ASCII 表示类型不能正常传输
它的ASCII模式根本不能正常传输文件。
用我自己编写的服务器程序,发现客户端会提前关闭数据连接(data connection),导致服务器在向关闭的套接字写入时产生SIGPIPE
信号。(这个信号需要处理,否则服务器程序会abort()
退出)
以为是我的问题,使用了权威的vsftpd
来测试,发现也是同样结果。
抓包观察,可以看到一个很抽象的地方:客户端tnftp发送TYPE A
来向服务器vsftpd请求使用ASCII模式传输,服务器也响应了 “200 Switching to ASCII mode”,结果在RETR Country.mmdb
的时候,又提示了BINARY mode,前后矛盾。
实际上,即使是将二进制文件中的\r
全部去掉,并且把\n
换成协议要求的\r\n
,再以ASCII模式传输,仍然会出现这样的问题,很难理解tnftp里面是如何处理的。
2. 传输模式不一致
实测还发现,如果服务器不支持SYST命令(例如返回 ”502 command is not implememnted“),那么tnftp会默认使用ASCII表示类型传输。
但是,如果服务器支持SYST,且服务器是UNIX/Linux系统(返回 “215 UNIX Type: L8”),那么tnftp就会默认使用BINARY模式传输(也就是表示类型为图像/binary)。
3. SYSY和SIZE
实测发现,如果支持SYST命令,但是不支持SIZE命令,那么会出现很奇怪的现象:RETR
下载文件时,会先发送PASV
请求,紧跟着再发送PORT
请求,搞不懂什么情况。
(服务器如果按照串行来处理命令,就会因为PASV
导致服务器阻塞在的accept()
等待客户端连接,但是PORT
又导致客户端用accept()
等待服务器连接。客户端卡住不能用。)
4. 代码可读性极差
下载了一份tnftp的代码,可读性很差。
三四百行的函数随处可见,goto满天飞,非常琐碎。很佩服开发者能够把它给维护起来。
大概就是下面这张图: