其实我们做Ftp客户端工具只不过是用一个winsocket连接上Ftp服务器,然后象其发送命令。在这个过程中,我们依靠发送——响应的机制。即发送Ftp命令——接收返回的响应信息——分析该信息——执行相关操作——发送下一条命令。在一般意义上,有一个socket用来连接Ftp服务器的相关端口(如默认的21),它负责Ftp命令的发送和接收返回的响应信息。一些操作如“进入目录”,“删除文件”,依靠这个socket发送一条命令就可完成了。然而对于有数据传输的操作,主要是显示远端目录列表,上传、下载文件,我们不得不依靠另一个socket来完成。在进行这种操作之前,必须发送PASV命令,它返回了227开头的信息,在括号中有以逗号隔开的六个数字,前四个指服务器的地址,关键是最后两个,将倒数第二个乘256再加上最后一个数字,其结果就是Ftp服务器开放的用于下一条命令来进行数据传输的端口。如我们得到227 Entering Passive Mode (127,0,0,1,4,18),那么端口号是4*256+18=1042。我们用一个socket来连接这个端口,之后,我们可根据具体的操作(显示目录LIST,上传文件STOR,下载RETR)来发送命令。返回的响应代码为125开头,也就是连接打开了,可以开始传输数据,这时就可用socket的发送或接收方法来传输数据。完成之后,服务器会返回代码226 Transfer complete,表明数据传输完成。值得注意的是,我们最好不要一次发送多条命令,例如我们要回到上层目录并且显示这个目录,我们得发送CDUP,PASV,LIST,我们不能一下子发送:CDUP/r/n, PASV/r/n, LIST/r/n。而是发送完CDUP之后等待其响应代码,然后再发送后面一条。当PASV返回之后,我们打开另一个socket连接到相关端口上。然后发送LIST,返回125之后在开始接收数据,最后返回226表明完成。对于上传和下载也是差不多的过程(下载之前要先取得文件的大小)。
前三个字符220表示客户端与服务器成功连接,后面的字符会因服务器的不同而不同,但我们只关心前三个字符。
客户端发送用户名给服务器,如:USER guo
如果服务器找到用户名guo,将返回字符串,如:331 User name okay, need password.
接着客户端应发送密码给服务器,如:PASS aaa
密码正确,返回如:230 User logged in, proceed.
如果用户名或密码认证没通过,返回如:530 Not logged in.
用户名也可以使用匿名,如:USER anonymous
返回如:331 Anonymous access allowed,send identity (e-mail name) as password.
FTP协议用两个连接来达到客户机与服务器之间交换数据的目的。刚才建立了第一个连接——控制连接,它用于传送命令和响应。我们还要建立第二个连接——数据连接,用于数据传输。FTP提供了两种方式来建立数据连接,一种用PORT命令,一种用PASV命令。我们使用后者。客户端发送PASV命令给服务器,服务器返回IP地址和端口号,用来提供给客户端进行数据连接。如:227 Entering Passive Mode (10,175,125,49,9,17)
括号里6个数字中前4个数字表示IP地址10.175.125.49,后2个数字表示端口号,这2个数字按如下公式计算端口号:9*256+17=2321
这样,客户端就可用IP地址10.175.125.49和端口号2321连接服务器,建立数据连接。
● LIST命令
该命令用于获取FTP服务器的目录列表,服务器操作成功后返回:
150 Opening ASCII mode data connection for /bin/ls.
目录列表要通过数据连接进行传输,若数据连接没有准备好,则返回:
425 Can’t open data connection.
目录列表传到客户端后,返回:
226 Transfer complete.
该命令用于改变服务器的工作目录。如:CWD BOOKS
服务器操作成功返回:250 Directory changed to /c:/BOOKS.
若没有找到该目录,返回:550 /c:/BOOK: No such file or directory.
该命令用于文件下载。如RETR a.txt
服务器返回:150 Opening ASCII mode data connection for a.txt (124 bytes).
226 Transfer complete.
该命令用于上传文件。如:STOR b.txt
服务器返回:150 Opening ASCII mode data connection for b.txt.