linux下FTP编程socket文档格式.docx
《linux下FTP编程socket文档格式.docx》由会员分享,可在线阅读,更多相关《linux下FTP编程socket文档格式.docx(18页珍藏版)》请在冰点文库上搜索。
被动模式下,当开启一个FTP连接时,客户端打开两个任意的本地端口(N>
1024和N+1)。
第一个端口连接服务器的21端口,提交PASV命令。
然后,服务器会开启一个任意的端口(P>
1024),返回如“227enteringpassivemode(127,0,0,1,4,18)”。
它返回了227开头的信息,在括号中有以逗号隔开的六个数字,前四个指服务器的地址,最后两个,将倒数第二个乘256再加上最后
一个数字,这就是FTP服务器开放的用来进行数据传输的端口。
如得到227enteringpassivemode(h1,h2,h3,h4,p1,p2)那么端口号是p1*256+p2,ip地址为h1.h2.h3.h4这意味着在服务器上有一个端口被开放。
客户端收到命令取得端口号之后,会通过N+1号端口连接服务器的端口P,然后在两个端口之间进行数据传输。
主要用到的FTP命令
FTP每个命令都有3到4个字母组成,命令后面跟参数,用空格分开。
每个命令都以"
\r\n"
结束。
要下载或上传一个文件,首先要登入FTP服务器,然后发送命令,最后退出。
这个过程中,主要用到的命令有USER、PASS、SIZE、REST、CWD、RETR、PASV、PORT、QUIT。
USER:
指定用户名。
通常是控制连接后第一个发出的命令。
“USERgaoleyin”:
用户名为gaoleyi
登录。
PASS:
指定用户密码。
该命令紧跟USER命令后。
“PASSgaoleyin”:
密码为gaoleyi。
SIZE:
从服务器上返回指定文件的大小。
“SIZEfile.txtn”如果file.txt文件存在,则返回该文件
的大小。
CWD:
改变工作目录。
如:
“CWDdirnamen”。
PASV:
让服务器在数据端口监听,进入被动模式。
“n”。
PORT:
告诉FTP服务器客户端监听的端口号,让FTP服务器采用主动模式连接客户端。
“PORTh1,h2,h3,h4,p1,p2。
”
RETR:
下载文件。
“RETRfile.txtn”下载文件file.txt。
STOR:
上传文件。
“STORfile.txtn”上传文件file.txt。
REST:
该命令并不传送文件,而是略过指定点后的数据。
此命令后应该跟其它要求文件传输的
FTP命令。
“REST100n”重新指定文件传送的偏移量为100字节。
QUIT:
关闭与服务器的连接。
FTP响应码
客户端发送FTP命令后,服务器返回响应码。
响应码用三位数字编码表示:
第一个数字给出了命令状态的一般性指示,比如响应成功、失败或不完整。
第二个数字是响应类型的分类,如2代表跟连接有关的响应,3代表用户认证。
第三个数字提供了更加详细的信息。
第一个数字的含义如下:
1表示服务器正确接收信息,还未处理。
2表示服务器已经正确处理信息。
3表示服务器正确接收信息,正在处理。
4表示信息暂时错误。
5表示信息永久错误。
第二个数字的含义如下:
0表示语法。
1表示系统状态和信息。
2表示连接状态。
3表示与用户认证有关的信息。
4表示未定义。
5表示与文件系统有关的信息。
Socket编程的几个重要步骤
Socket客户端编程主要步骤如下:
1.socket()创建一个Socket
2.connect()与服务器连接
3.write()和read()进行会话
4.close()关闭Socket
Socket服务器端编程主要步骤如下:
2.bind()
3.listen()监听
4.accept()接收连接的请求
5.write()和read()进行会话
6.close()关闭Socket
实现FTP客户端上传下载功能
F面让我们通过一个例子来对FTP客户端有一个深入的了解。
本文实现的FTP客户端有下列功能:
1.客户端和FTP服务器建立Socket连接。
2.向服务器发送USER、PASS命令登录FTP服务器。
3.使用PASV命令得到服务器监听的端口号,建立数据连接
4.使用RETR/STOR命令下载/上传文件。
5.在下载完毕后断开数据连接并发送QUIT命令退出。
本例中使用的FTP服务器为filezilla。
在整个交互的过程中,控制连接始终处于连接的状态,数据连接在每传输一个文件时先打开,后关闭。
客户端和FTP服务器建立Socket连接
当客户端与服务器建立连接后,服务器会返回220的响应码和一些欢迎信息
图1.客户端连接到服务器端
FTPCliscii
FTPStrver
I
socket^
Xbindj
VTime
清单1.客户端连接到FTP服务器,接收欢迎信息
SOCKETcontrol_sock;
structhostent*hp;
structsockaddr_inserver;
memset(&
server,0,sizeof(structsockaddr_in));
/*初始化socket*/
control_sock=socket(AF」NET,SOCK_STREAM,0);
hp=gethostbyname(server_name);
memcpy(&
server.sin_addr,hp->
h_addr,hp->
h_length);
server.sin_family=AF_INET;
server.sin_port=htons(port);
/*连接到服务器端*/
connect(control_sock,(structsockaddr*)&
server,sizeof(server));
/*客户端接收服务器端的一些欢迎信息*/
read(control_sock,read_buf,read_len);
客户端登录FTP服务器
当客户端发送用户名和密码,服务器验证通过后,会返回230的响应码。
然后客户端就可以向服
务器端发送命令了。
图2.客户端登录FTP服务器
清单2.客户端发送用户名和密码,登入FTP服务器
/*命令”n”*/
sprintf(send_buf,"
USER%s\r\n"
username);
/*客户端发送用户名到服务器端*/
write(control_sock,send_buf,strlen(send_buf));
/*客户端接收服务器的响应码和信息,正常为”331Usernameokay,needpassword.”*/
/*命令”PASSpassword'
"
n”*/
sprintf(send_buf,"
PASS%s\r\n"
password);
/*客户端发送密码到服务器端*/
/*客户端接收服务器的响应码和信息,正常为”230Userloggedin,proceed.”*/
客户端让FTP服务器进入被动模式
当客户端在下载/上传文件前,要先发送命令让服务器进入被动模式。
服务器会打开数据端口并监听。
并返回响应码227和数据连接的端口号。
图3.客户端让服务器进入被动模式
FTPSer\TTfTPClient
1
r
1—
—
stndi,'
'
i
1PASXrcT
stud()
rrtTMi
fMckenJ
dbindC)
•hsTeti('
ponpl
Time1i
ir1
■■
清单3.让服务器进入被动模式,在数据端口监听
/*命令”PASV\r\n”*/
PASV\r\n"
);
/*客户端告诉服务器用被动模式*/
/*客户端接收服务器的响应码和新开的端口号,
*正常为”227Enteringpassivemode(<
h1,h2,h3,h4,p1,p2>
)”*/
客户端通过被动模式下载文件
当客户端发送命令下载文件。
服务器会返回响应码150,并向数据连接发送文件内容
FTP
reeve;
sendf:
"
231z
mi)
sendCccutenr
A
da:
asocket
stndfi
CAWdiriiain?
rn
rtcv(i
send()
LSIZZfilename^'
n
rt<
vO
sendf
茫TKrti'
r?
cv('
rtcvuand记卫ei"
filecDiitmr
Time
昶tidi;
150"
图4.客户端从FTP服务器端下载文件
清单4.客户端连接到FTP服务器的数据端口并下载文件
/*连接服务器新开的数据端口*/
connect(data_sock,(structsockaddr*)&
/*命令”CWDdirname\r\n”*/
CWD%s\r\n"
dirname);
/*客户端发送命令改变工作目录*/
/*客户端接攵服务器的响应码和信息,正常为”250Commandokay.”*/read(control_sock,read_buf,read_len);
/*命令”SIZEfilename\r\n”*/sprintf(send_buf,"
SIZE%s\r\n"
filename);
/*客户端发送命令从服务器端得到下载文件的大小*/write(control_sock,send_buf,strlen(send_buf));
/*客户端接收服务器的响应码和信息,正常为”213<
size>
”*/read(control_sock,read_buf,read_len);
/*命令”RETRfilename\r\n”*/sprintf(send_buf,"
RETR%s\r\n"
/*客户端发送命令从服务器端下载文件*/write(control_sock,send_buf,strlen(send_buf));
/*客户端接收服务器的响应码和信息,正常为”150Openingdataconnection.”*/read(control_sock,read_buf,read_len);
/*客户端创建文件*/file_handle=open(disk_name,CRFLAGS,RWXALL);
for(;
;
){
/*客户端通过数据连接从服务器接收文件内容*/read(data_sock,read_buf,read_len);
/*客户端写文件*/write(file_handle,read_buf,read_len);
}
/*客户端关闭文件*/rc=close(file_handle);
客户端退出服务器当客户端下载完毕后,发送命令退出服务器,并关闭连接。
服务器会返回响应码
仃Time
d託Iiltl
recvQ
sendi:
LQUTrrT
clo^ti!
^on?
ol沁
清单5.客户端关闭数据连接,退出FTP服务器并关闭控制连接
/*客户端关闭数据连接*/
close(data_sock);
/*客户端接收服务器的响应码和信息,正常为”226Transfercomplete.”*/
/*命令”QUIT\r\n”*/
QUIT\r\n"
/*客户端将断开与服务器端的连接*/
/*客户端接收服务器的响应码,正常为”200Closesconnection.”*/
/*客户端关闭控制连接*/
close(control_sock);
至此,下载文件已经完成。
需要注意的是发送FTP命令的时候,在命令后要紧跟“r\n”否则服务
器不会返回信息。
回车换行符号“n”是FTP命令的结尾符号,当服务器接收到这个符号时,认
为客户端发送的命令已经结束,开始处理。
否则会继续等待。
让我们来看一下FTP服务器这一端的响应情况:
清单6.客户端下载文件时,FTP服务器的响应输岀
(notloggedin)(127.0.0.1)>
Connected,sendingwelcomemessage...
(notloggedin)(127.0.0.1)>
220-FileZillaServerversion0.9.36beta
220hellogaoleyi
(notloggedin)(127.0.0.1)>
USERgaoleyi
331Passwordrequiredforgaoleyi
PASS*********
gaoleyi(127.0.0.1)>
230Loggedon
PWD
257"
/"
iscurrentdirectory.
SIZEfile.txt
2134096
PASV
227EnteringPassiveMode(127,0,0,1,13,67)
RETRfile.txt
150Connectionaccepted
226TransferOK
QUIT
221Goodbye
首先,服务器准备就绪后返回220。
客户端接收到服务器端返回的响应码后,相继发送“USERusername”和“PASSpassworc命令登录。
随后,服务器返回的响应码为230开头,说明客户端已经登入了。
这时,客户端发送PASV命令让服务器进入被动模式。
服务器返回如“227EnteringPassiveMoce(127,0,0,1,13,67),客”户端从中得到端口号,然后连接到服务器的数据端口。
接下来,客户端发送下载命令,服务器会返回响应码150,并从数据端口发送数据。
最后,服务器返回
“226transfercomplete表明数据传输完成。
需要注意的是,客户端不要一次发送多条命令,例如我们要打开一个目录并且显示这个目录,我
们得发送CWDdirname,PASV,LIST。
在发送完CWDdirname之后等待响应代码,然后再发送后面一条。
当PASV返回之后,我们打开另一个Socket连接到相关端口上。
然后发送LIST,返回125之后在开始接收数据,最后返回226表明完成。
在传输多个文件的过程中,需要注意的是每次新的传输都必须重新使用PASV获取新的端口号,接收完数据后应该关闭该数据连接,这样服务器才会返回一个2XX成功的响应。
然后客户端可以继续下一个文件的传输。
上传文件与下载文件相比,登入验证和切换被动模式都如出一辙,只需要改变发送到服务器端的命令,并通过数据连接发送文件内容。
客户端通过被动模式向服务器上传文件
当客户端发送命令上传文件,服务器会从数据连接接收文件。
sodsEi
contiecq;
:
rcda:
^etidr
C^T)dirnainfr11"
recvij
setidii
STOXfilenatrifr(T
Tun?
r^cvQ
readf;
mH5?
tidr)
recvQ唯亡content1:
and:
客户端通过主动模式向服务器上传文件
F面将介绍客户端用主
到目前为止,本文介绍的都是客户端用被动模式进行文件的上传和下载动模式下载文件。
图7.用主动模式从FTP服务器下载文件
Tinif
socketj
biadQ
丞辻ti〔:
topor:
pl*25(5-p2
&
mdf)“PORT
Phl'
Mrh辺u£
i:
二卡药riT
ftCVlj
sendi.i
RZISLfilenamer:
rf'
ivr)
acceplQ
teceri:
andwritet'
i"
fl>
conc*n:
'
:
清单7.用主动模式从FTP服务器下载文件的示例C程序
SOCKETdata_sock;
data_sock=socket(AF」NET,SOCK_STREAM,0);
structsockaddr_inname;
name.sin_family=AF_INET;
name.sin_addr.s_addr=htons(INADDR_ANY);
server_port=p1*256+p2;
length=sizeof(name);
name.sin_port=htons(server_port);
bind(server_sock,(structsockaddr*)&
name,length);
structsockaddr_inclient_name;
length=sizeof(client_name);
/*客户端开始监听端口p1*256+p2*/
listen(server_sock,64);
/*命令”PORT\r\n”*/
PORT1287,0,0,1,%d,%d\r\n"
p1,p2);
write(control_sock,send_buf,strlen(send_buf));
/*客户端接收服务器的响应码和信息,正常为”200Portcommandsuccessful”*