现在的位置: 首页 > 综合 > 正文

【Linux】FTP文件下载

2018年04月02日 ⁄ 综合 ⁄ 共 4458字 ⁄ 字号 评论关闭

代码来源于网络,记录下,方便日后使用(适用于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

 

 

抱歉!评论已关闭.