課程設計是實現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實現也都具有這一未被寫在文檔上的特性。