代码来源于网络,记录下,方便日后使用(适用于Linux平台)
/*使用FTP协议获取服务器上的文件(Passive方式) 1 在客户端创建一个SOCK_STREAM类型的套接字,并与FTP服务器端的21号命令端口连接(因为FTP服务器的21号端口在侦听); 2 再创建一个SOCK_STREAM类型的数据套接字,准备与FTP服务器端的数据端口进行通信(因为是Passive方式,所以服务器端的数据端口不是20号了) 3 发送用户名、密码到21号命令端口 4 发送PASV,从返回的字符串里取出的服务器上的数据端口号,然后客户端通过connect与该端口进行连接(此时服务器端的数据端口在侦听) 5 然后客户端就可以通过这两个套接字与服务器端进行通信了 使用FTP协议获取服务器上的文件(Port方式) 1 在客户端创建一个SOCK_STREAM类型的套接字,并与FTP服务器端的21号命令端口连接(因为FTP服务器的21号端口在侦听); 2 再创建一个SOCK_STREAM类型的数据套接字,准备与FTP服务器端的数据端口进行通信(因为是Port方式,所以服务器端的数据端口是20号) 3 绑定本地地址和数据套接字,然后就侦听,并等待服务器来连接(此时客户端的数据套接字要listen和accept) 3 发送用户名、密码到21号命令端口 4 发送PORT,等待服务器的数据端口来连接 5 连接成功后,客户端就可以通过这两个套接字与服务器端进行通信了 我这个程序是在linux下运行的; 在我的程序中:用户名是leetow,口令是leetow,FTP服务器的IP是192.168.1.90; 程序运行格式:程序名 要下载的文件名 */ #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <errno.h> #include <stdio.h> #include <strings.h> #include <netinet/in.h> #include <string.h> #include <arpa/inet.h> #include <netdb.h> #define FTP_SERVER "192.168.1.90" int main(int argc,char* argv[]) { int sk_data,sk_ctrl; //客户端的两个套接字,分别与服务器端的数据端口、命令端口端口进行通信 struct sockaddr_in addr_data,addr_ctrl; //服务器的两个地址,分别与客户端的数据端口、命令端口端口进行通信 struct in_addr inp; //我这里的用户名是leetow,口令是leetow char bufrecv[100],user[]="USER leetow\r\n",passwd[]="PASS leetow\r\n",pasv[]="PASV\r\n"; char size[30]="SIZE ",type[]="TYPE A\r\n",download[30]="RETR ",quit[100]="QUIT\r\n",line_end[]="\r\n"; char filebuf[50000],str[100]; //文件缓冲区 int lensnd,lenrecv,err; int a1,a2,a3,a4,p1,p2;//从服务器返回的地址和端口 FILE *fp; int len; //获得文件名 if(argc!=2) { printf("Usage:%s filename \n", argv[0]); return -1; } //补齐文件大小与下载文件的命令 strcat(size,argv[1]); strcat(size,line_end); strcat(download,argv[1]); strcat(download,line_end); //create two socket for SOCK_STREAM sk_data=socket(AF_INET,SOCK_STREAM,0); sk_ctrl=socket(AF_INET,SOCK_STREAM,0); if(sk_data<0 ) { perror("creat socket sk_data error"); return -1; } if(sk_ctrl < 0 ) { perror("creat socket sk_ctrl error"); close(sk_data); return -1; } //与服务器上的21号端口连接 bzero(&addr_ctrl,sizeof(struct sockaddr_in)); inet_aton(FTP_SERVER, &inp); //服务器IP地址 addr_ctrl.sin_family=AF_INET; addr_ctrl.sin_addr=inp; addr_ctrl.sin_port=htons(21); //FTP命令端口 //connect to server err=connect(sk_ctrl,(struct sockaddr*)&addr_ctrl,sizeof(struct sockaddr)); if(-1==err) { perror("connect 21 error"); close(sk_data); close(sk_ctrl); return -1; } //输出服务器端的连接成功的信息 bzero(bufrecv,100); lenrecv=recv(sk_ctrl,bufrecv,100,0); if(lenrecv>0) { printf("connect 21 successfully:%s\n",bufrecv); } //发送用户名 lensnd=send(sk_ctrl,user,strlen(user),0); if(lensnd>0) { bzero(bufrecv,100); recv(sk_ctrl,bufrecv,100,0); printf("user name:%s\n",bufrecv); } //发送口令 lensnd=send(sk_ctrl,passwd,strlen(passwd),0); if(lensnd>0) { bzero(bufrecv,100); recv(sk_ctrl,bufrecv,100,0); printf("password:%s\n",bufrecv); } //PASV lensnd=send(sk_ctrl,pasv,strlen(pasv),0); if(lensnd>0) { bzero(bufrecv,100); recv(sk_ctrl,bufrecv,100,0); printf("pasv:%s\n",bufrecv); sscanf(bufrecv,"%*[^(]%[^)]",str); //字符串中从"("开始一直到")"之间的字符存到str中,包括"(" sscanf(str,"(%d,%d,%d,%d,%d,%d",&a1,&a2,&a3,&a4,&p1,&p2); printf("p1,p2=%d,%d\n",p1,p2); printf("p1*256+p2=%d\n",p1*256+p2); } //指定服务器的数据端口 bzero(&addr_data,sizeof(struct sockaddr_in)); inet_aton(FTP_SERVER, &inp); //服务器IP地址 addr_data.sin_family=AF_INET; addr_data.sin_addr=inp; addr_data.sin_port=htons(p1*256+p2); err=connect(sk_data,(struct sockaddr*)&addr_data,sizeof(struct sockaddr)); if(-1==err) { perror("connect 20 error"); close(sk_data); close(sk_ctrl); return -1; } //获得文件大小 lensnd=send(sk_ctrl,size,strlen(size),0); if(lensnd>0) { bzero(bufrecv,100); recv(sk_ctrl,bufrecv,100,0); printf("sz:%s\n",bufrecv); sscanf(bufrecv,"%d %d",&a1,&len); printf("a1,len=%d,%d\n",a1,len); } //从服务器上获得文件 lensnd=send(sk_ctrl,download,strlen(download),0); if(lensnd>0) { bzero(bufrecv,100); recv(sk_ctrl,bufrecv,100,0); printf("get file:%s\n",bufrecv); } //本地建文件并写入数据 fp=fopen(argv[1],"w"); if(NULL==fp) { printf("fopen error:\n"); close(sk_data); close(sk_ctrl); return -1; } lenrecv=recv(sk_data,filebuf,len,0); if(lenrecv>0) { fwrite(filebuf,len,1,fp); fclose(fp); } //退出 lensnd=send(sk_ctrl,quit,strlen(quit),0); if(lensnd>0) { bzero(bufrecv,100); recv(sk_ctrl,bufrecv,100,0); printf("quit:%s\n",bufrecv); printf("send qexit successful\n"); } close(sk_data); close(sk_ctrl); return 0; }
Makefile
#CROSS = arm-hisiv100nptl-linux- CXX = $(CROSS)g++ RM=rm -f CFLAGS = -Wall -Os -DLINUX ALL=a all: $(ALL) a: a.cpp $(CXX) $(CFLAGS) -o $@ $^ clean: $(RM) *.o $(ALL)
运行
[zcm@ftp #49]$./a a.txt connect 21 successfully:220 Microsoft FTP Service user name:331 Password required for zcm. password:230 User logged in. pasv:227 Entering Passive Mode (192,168,1,90,143,39). p1,p2=143,39 p1*256+p2=36647 sz:213 80 a1,len=213,80 get file:125 Data connection already open; Transfer starting. quit:226 Transfer complete. send qexit successful