# FTP 协议
FTP 协议有两种工作方式:PORT 方式和 PASV 方式,中文意思为主动式和被动式。
相比于 HTTP,FTP 协议要复杂得多。复杂的原因,是因为 FTP 协议要用到两个 TCP 连接,一个是命令链路,用来在 FTP 客户端与服务器之间传递命令;另一个是数据链路,用来上传或下载数据。
PORT(主动)方式的连接过程是:服务器开放一个端口,通知客户端连接,服务端接受连接,建立一条命令链路。当需要传送数据时,客户端在命令链路上用 PORT 命令告诉服务器:“我打开了一个 1024 + 的随机端口,你过来连接我”。于是服务器从 20 端口向客户端的 1024 + 随机端口发送连接请求,建立一条数据链路来传送数据。
PASV(被动)方式的连接过程是:客户端向服务器的 FTP 端口(默认是 21)发送连接请求,服务器接受连接,建立一条命令链路。当需要传送数据时,服务器在命令链路上用 PASV 命令告诉客户端:“我打开了一个 1024 + 的随机端口,你过来连接我”。于是客户端向服务器的 1024 + 端口发送连接请求,建立一条数据链路来传送数据。
从上面可以看出,两种方式的命令链路连接方法是一样的,而数据链路的建立方法就完全不同。而 FTP 的复杂性就在于此。
# 分布式传输模式下的区别
PASV 无法工作在分布式传输模式下,用一个例子来简单的说明:
假设 master 是 10.0.0.1,而 slave 有三个 10.1.0.1, 10.1.0.2, 10.2.0.1。作为客
户端所在 IP 是 192.168.254.1,现在要下载一个文件 file.zip。
# 被动模式下
首先客户端发出 PASV 命令。
位于 10.0.0.1 的 master 收到这条命令后,它会想我有三个 slave 地址,我应该返回哪
一个呢?因为我并不知道接下来会发生什么啊。于是 master 便把自己的地址返回了。
因此你的客户端得到这样的返回:227 Entering Passive Mode (10,0,0,1,13,236)
接着你的客户端发出 RETR file.zip 的命令。
master 收到以后在自己的数据库里一查,在 10.1.0.2 上有,但是刚才已经返回了
10.0.0.1 给客户端,客户端连接 10.0.0.1 的端口失败,见鬼。
# 主动模式下
客户端发出 PORT 192,168,254,1,12,345
master 收到命令后就记住了将来要连接的地址和端口。
接着你的客户端发出 RETR file.zip 的命令。
同前所述,此时 master 就可以告诉 10.1.0.2 的 slave 让它连接 192.168.254.1,把
file.zip 上传。所以在 PORT 方式下毫无问题。
# 如何解决 PASV 下的问题
增加一条 PRET 命令,这条命令的唯一作用就是在发送 PASV 之前预先告诉 master 接下来要做的事情。
这次客户端先发出 PRET RETR file.zip
master 收到命令后知道你将要获取 file.zip,于是实现找到该文件所在位置。
接着客户端发出 PASV
这时 master 已经预先知道你接下来要做什么了,于是它应答 10.1.0.2 的地址。得到
这样的返回:227 Entering Passive Mode (10,1,0,2,13,236)
然后客户端再发出 RETR file.zip
这时客户端就连接上 10.1.0.2 开始下载了。