课程设计是实现FTP客户端和服务端。
FTP
实验内容
我实现了FTP的客户端和服务端,除了PUT、GET、?等还实现了SITE、MKD、RMD、RNFR、SIZE等大量命令,以及active/passive模式的切换、ascii/image类型的RETR等。
客户端
源代码为src/client/目录及src/*.cc,src/*文件为客户端与服务端共用。
命令行选项帮助
% build/ftp -h
FTP client.
Usage: build/ftp [options] [uri]
Options:
-d, --debug
-h, --help display this help and exit
-q, --quiet
Report bugs to i@maskray.me
命令行提示符
使用了ANSI escape code产生颜色。
命令行补全
使用了readline库进行命令补全,相关代码在src/client/completion.cc里。如下终端会话为键入了命令的开头字母后按TAB补全得到的。
% build/ftp 127.1
ftp >>= l
list login ls
ftp >>= m
md mkdir
cat命令
以ASCII data type显示服务端文件。
ftp /upload >>= cat ii
ddfsdafffffffffffffffffffffffffffffffffffffff
命令行选项:-d 调试
-d选项会输出客户端与服务端的所有通信内容。
% build/ftp -d 127.1
--> 220 ProFTPD 1.3.4d Server (ProFTPD Default Server) [::ffff:127.0.0.1]
ftp >>= login
Login (anonymous):
--> USER anonymous
--> 331 Anonymous login ok, send your complete email address as your password
Password:
--> PASS
--> 230 Anonymous access granted, restrictions apply
--> PWD
--> 257 "/" is the current directory
ftp / >>= get ii -o ggg
--> PASV
--> 227 Entering Passive Mode (127,0,0,1,141,120).
--> TYPE I
--> 200 Type set to I
--> RETR ii
--> 550 ii: No such file or directory
ftp /upload >>= cd upload
--> CWD upload
--> 250 CWD command successful
--> PWD
--> 257 "/upload" is the current directory
ftp /upload >>= get ii -o ggg
--> PASV
--> 227 Entering Passive Mode (127,0,0,1,163,63).
--> TYPE I
--> 200 Type set to I
--> RETR ii
--> 150 Opening BINARY mode data connection for ii (46 bytes)
ftp /upload >>=
Active模式
默认使用passive模式(FTP协议默认使用active模式),active命令可以切换到active模式。
ftp / >>= active
ftp / >>= ls
--> PORT 127,0,0,1,209,75
--> 200 PORT command successful
--> LIST
--> 150 Opening ASCII mode data connection for file list
-rw-r--r-- 1 ftp ftp 1907 Sep 28 05:44 10.cc
drwxr-xr-x 2 ftp ftp 4096 Dec 26 13:53 a
--> 226 Transfer complete
ftp / >>=
IPv6支持
当服务端地址为IPv6时,会选择使用EPSV和EPRT
代替PASV和PORT。
% build/ftp -d ::1
<-- 220 ProFTPD 1.3.4d Server (ProFTPD Default Server) [::1]
ftp >>= login
Login (anonymous):
--> USER anonymous
<-- 331 Anonymous login ok, send your complete email address as your password
Password:
--> PASS
<-- 230 Anonymous access granted, restrictions apply
--> PWD
<-- 257 "/" is the current directory
ftp / >>= ls
--> EPSV
<-- 229 Entering Extended Passive Mode (|||1226|)
--> LIST
<-- 150 Opening ASCII mode data connection for file list
drwxr-xr-x 2 ftp ftp 4096 Feb 1 2013 distfiles
drwxrwxrwx 9 ftp ftp 4096 Dec 26 13:54 upload
<-- 226 Transfer complete
ftp / >>= active
ftp / >>= ls
--> EPRT |2|::1|40632|
<-- 200 EPRT command successful
--> LIST
<-- 150 Opening ASCII mode data connection for file list
drwxr-xr-x 2 ftp ftp 4096 Feb 1 2013 distfiles
drwxrwxrwx 9 ftp ftp 4096 Dec 26 13:54 upload
<-- 226 Transfer complete
ftp / >>=
帮助
ftp >>= ?
All commands: active, cat, cd, cdup, chdir, chmod, connect, close, debug, dir, get, help, lcd, login, list, lpwd, ls, md, mkdir, mv, open, passive, put, pwd, quit, quote, rhelp, rd, rmdir, site, size, ?
ftp >>= ? get
Usage: get [options] rfile
Options:
-a, --ascii use ascii mode (default: binary)
-o, --output local file name (default: basename of rfile)
-h, --help help
服务端
源代码为src/server/目录及src/*.cc,src/*文件为客户端与服务端共用。
IPv6支持
使用-6命令行选项监听IPv6地址而非IPv4地址。
daemon模式
默认使用daemon(3)脱离控制终端并把stdin、stdout、stderr重定向至/dev/null。可以加上选项-n防止变为daemon。
% sudo build/ftpd -6nd /tmp
--> 220 Ready
<-- USER anonymous
--> 331 Anonymous login ok, send your complete email address as your password
<-- PASS
--> 230 Anonymous access granted
<-- PWD
--> 257 "/tmp" is the current directory
监听端口
选项-p用于指定监听端口。
% build/ftpd /tmp -p 2121
passive模式端口选择
指定sockaddr_in的sin_port字段为0,这样bind会随机选择一个端口。这是4.2BSD
socket API的行为,大多数socket实现也都具有这一未被写在文档上的特性。