分类: C/C++
2010-03-21 22:01:11
在进一步分析代码之前,先复习一下FTP协议,下图是FTP的结构图。
客户端和服务器是通过两个连接来进行通讯的:
一个是控制连接,也就是传输些控制命令,客户端发出FTP命令,服务器给出应答,例如:USER,PASS命令等等。这个连接中,FTP服务器的端 口就是熟知的21端口,连接是由客户端发起的,例如:ftp 192.168.0.1。有一点注意,用户是通过“用户接口”来操作的,一般的用户接口是指cuteFTP这些FTP客户端,或者ftp.exe这种命令 行程序,用户在用户接口使用的是ftp命令,如ls, get, cd等,这些ftp命令并不是真正与FTP服务器交互的命令,这些ftp命令还需要由“用户协议解释器”翻译成真正的ftp协议命令,如USER, PASS,才能与服务器进行交互。
一个是数据连接,即真正的文件传输是在这个连接上进行的。服务器端的数据连接端口是20,客户端的数据连接端口是随机生成的。数据连接只在传输文件 时存在,文件传完后,这个连接就断了,如果需要再次传送文件,会再次建立一个数据连接(客户端的端口是随机的,不一定是上次的那个)。数据连接的模式有两 种,一种是主动方式,一种是被动方式,两者的区别在于数据连接是由谁发起。
我们来看一个典型的FTP交互过程,用的是windows的ftp.exe程序,先建立一个连接,然后ls看一下文件列表,用get命令下
载一个文件,最后quit关闭。下面-d选项可以显示交互的细节,注意-->开头的行是ftp客户端发给FTP服务器的请求,3个数字开头的行是服
务器的应答,如220, 331等开头的行:
C:\>ftp -d localhost
Connected to dell.
220-FileZilla Server
version 0.9.18 beta
220-written by Tim Kosse ()
220 Please visit
User
(dell:(none)): robert
---> USER robert
331 Password required
for robert
Password:
---> PASS test
230 Logged on
ftp>
ls
---> PORT 127,0,0,1,4,173
200 Port command successful
--->
NLST
150 Opening data channel for directory list.
Manual.txt
226
Transfer OK
ftp: 收到 175 字节,用时 0.00Seconds 175000.00Kbytes/sec.
ftp>
get Manual.txt
---> PORT 127,0,0,1,4,174
200 Port command
successful
---> RETR Manual.txt
150 Opening data channel for
file transfer.
226 Transfer OK
ftp: 收到 17319 字节,用时 0.09Seconds
192.43Kbytes/sec.
ftp> quit
---> QUIT
221 Goodbye
C:\>
刚开始,客户端发出建立连接的请求:
C:\>ftp -d localhost // 建立连接
Connected to
dell. // 连接已建立
然后服务器发送欢迎信息,并要求输入用户名:
220-FileZilla Server version 0.9.18 beta
220-written
by Tim Kosse ()
220
Please visit
User
(dell:(none)):
客户端输入用户名robert,然后回车:
---> USER robert //
ftp.exe生成FTP命令:USER,发送给服务器
服务器要求输入密码:
331 Password required for robert
Password:
客户端输入密码,然后回车:
---> PASS test // ftp.exe生成FTP命令:PASS,发送给服务器
服务器通过密码验证:
230 Logged on
客户端键入ls命令
ftp> ls
ftp.exe生成FTP命令:PORT,告诉服务器客户端的随机端口是什么
---> PORT 127,0,0,1,4,173
// 127,0,0,1是IP地址,4 * 256 + 173 = 1197是随机端口号
200 Port command
successful // 服务器响应PORT命令
---> NLST // 客户端发出NLST命令,要求列出文件列表
150
Opening data channel for directory list. //
服务器会在20端口与客户端的1197端口建立数据连接,传输数据,注意ls命令的结果是在“数据连接”中传输的
Manual.txt //
只有一个文件
226 Transfer OK // FTP服务器响应,传输完毕
ftp: 收到 175 字节,用时
0.00Seconds 175000.00Kbytes/sec. // FTP客户端显示的传输结果
下面客户端要求下载Manual.txt文件
ftp> get Manual.txt
---> PORT 127,0,0,1,4,174 // 告诉服务器客户端新的随机端口4 * 256 + 174 = 1198
200
Port command successful // // 服务器响应PORT命令
---> RETR Manual.txt //
告诉服务器下载Manual.txt文件
150 Opening data channel for file transfer. //
服务器会在20端口与客户端的1198端口建立数据连接,传输数据
226 Transfer OK // FTP服务器响应,传输完毕
ftp:
收到 17319 字节,用时 0.09Seconds 192.43Kbytes/sec. // FTP客户端显示的传输结果
最后客户端退出
ftp> quit
---> QUIT // 发出QUIT命令
221 Goodbye //
服务器最后响应
仔细阅读上面的交互过程,可以发现,用户手工输入的一个FTP命令,可能会被ftp.exe处理成与FTP服务器的多次交互。如ls,
get命令。