实验13 简单FTP 程序设计

简介:

实验13简单FTP 程序设计


实验目的:设计一个简单的FTP 客户端,支持用户登录,浏览目录列表,上传

文件和下载文件的功能。

实验内容:

程序的伪代码如下:

(假定FTP 用户名为user_name,密码为pass_word

主函数:

连接FTP 服务器的21 端口

等待FTP 服务器回应,若应答码不为220,则报错

FTP 服务器21 端口发送"USER user_name\r\n"字符串,等待FTP  回应,若

应答码不为331,则报错。

FTP 服务器21 端口发送"PASS pass_word\r\n"字符串,等待FTP 回应,若应

答码不为230,则报错:用户与密码不匹配。

while(1)

{

等待用户输入命令cmd;

cmd quit,则关闭套接字,退出程序

cmd ls dirlist_file(sock)

cmd put abc.xyz,则调用up_file(sock,abc.xyz)

cmd get abc.xyz,则调用down_file(sock,abc.xyz)

}

/*

函数名list_file

函数功能:显示ftp 服务器上文件列表

@sock : ftp  服务器控制端口对应的套接字

*/

函数list_file(int  sock)

{

//sock  对应了ftp 21 端口

sock 发送"TYPE I\r\n",等待应答码200

sock 发送"PASV\r\n",等待应答码227

sock 发送过来的字符串中寻找形如(xx,xx,xx,xx,xx, xx)的子串,从该字符串

中提取IP 地址和端口号。建立新套接字sock2,连接该IP 地址和端口号。

sock 发送"LIST\r\n"

sock2 中读取字符串,直到对方关闭


sock 中读取回应码,若不为226,则报错

}

/*

函数名up_file

函数功能:上传本地文件到ftp 服务器

@sock : ftp  服务器控制端口对应的套接字

@args: 要上传的文件名

*/

函数up_file(int  sock,char args)

{

在本地打开args 对应的文件,其文件指针为fp1

sock 发送"TYPE I\r\n",等待应答码200

sock 发送"PASV\r\n",等待应答码227

sock 发送过来的字符串中寻找形如(xx,xx,xx,xx,xx,xx)的子串,从该字符串

中提取IP 地址和端口号。建立新套接字sock2,连接该IP 地址和端口号。

sock 发送"STOR args 对应文件名\r\n"

fp1 指向的文件逐字节的读出,并且写入sock2 中,写完后关闭sock2

等待sock 的回应,回应码为226

}

/*

函数名up_file

函数功能:下载ftp 服务器文件到本地

@sock : ftp  服务器控制端口对应的套接字

@args: 要下载的文件名

*/

函数down_file(int  sock,char args)

{

在本地打开args 对应的文件,其文件指针为fp1

sock 发送"TYPE I\r\n",等待应答码200

sock 发送"PASV\r\n",等待应答码227

sock 发送过来的字符串中寻找形如(xx,xx,xx,xx,xx,xx)的子串,从该字符串

中提取IP 地址和端口号。建立新套接字sock2,连接该IP 地址和端口号。

sock 发送"SIZE args 对应文件名\r\n" ,若回应码不为213则没有这个文件

或通信过程出错。

sock 发送"RETR args 对应文件名\r\n" 

sock2 中内容逐字节的读出,并且写入fp1 的文件,写完后关闭sock2 fp1

等待sock 的回应,回应码应该为226,否则报错

}


附录:

代码实现:

#include  <sys/socket.h>

#include  <netinet/in.h>

#include  <arpa/inet.h>

#include  <fcntl.h>

#include  <unistd.h>

#include  <stdio.h>

#include  <errno.h>

#include  <netdb.h>

#include  <pwd.h>

#include  <termios.h>

#define BUFSIZE  1024

char buf[BUFSIZE];

char sendbuf[BUFSIZE];

void err_sys(char  *s)

{

printf("%s",s);

exit(-1);

};

void err_sysa(int  a,char *s)

{

printf("status=%d %s",a,s);

exit(-1);

};

void terminal_echo_off(int  fd)

{

struct termios oldterm;

tcgetattr(fd,&oldterm);

oldterm.c_lflag &=~ECHO;

tcsetattr(fd,TCSAFLUSH,&oldterm);

};

int active_listen()

{

int sockfd;

sockfd=socket(AF_INET,SOCK_STREAM,0);

if(sockfd==-1)

fprintf(stderr,"socket error!");

struct sockaddr_in localaddr;


localaddr.sin_family=AF_INET;

inet_aton("0.0.0.0",&localaddr.sin_addr);

localaddr.sin_port=0;

int bret=bind(sockfd,(struct  sockaddr*)&localaddr,sizeof localaddr);

if(bret==-1)printf("bind  error!\r\n");

return sockfd;

};

unsigned  int get_port(int fd)

{

struct sockaddr_in sa;

unsigned int port;

int sin_size=sizeof(struct sockaddr_in);

getsockname(fd,(struct sockaddr*)&sa,&sin_size);

port=ntohs(sa.sin_port);

return port;

};

void hexprint(char  *x)

{

int i=0;

while(x[i]!=0)

{

printf("%x  ",x[i]);

i++;

}

printf("\r\n");

};

void terminal_echo_on(int  fd)

{

struct termios oldterm;

tcgetattr(fd,&oldterm);

oldterm.c_lflag |= ECHO;

tcsetattr(fd,TCSAFLUSH,&oldterm);

};

void getaddrin(struct  sockaddr_in *pdest)

{

char *start=strchr(buf,'(');

start++;

char *end=strchr(buf,')');


*end=0;

char *pi;

for(pi=start;pi<end;pi++)

if(*pi==',')*pi=' ';

char ci1[4],ci2[4],ci3[4],ci4[4],ci5[4],ci6[4];

int c1,c2,c3,c4,c5,c6;

sscanf(start,"%s%s%s%s%s%s",ci1,ci2,ci3,ci4,ci5,ci6);

c1=atoi(ci1);

c2=atoi(ci2);

c3=atoi(ci3);

c4=atoi(ci4);

c5=atoi(ci5);

c6=atoi(ci6);

int ip=c1<<24|c2<<16|c3<<8|c4;

short port=c5<<8|c6;

struct sockaddr_in  dest;

pdest->sin_family=AF_INET;

pdest->sin_port=htons(port);

pdest->sin_addr.s_addr=htonl(ip);

};

void sendftp(const  char* cmd,int fd)

{

sprintf(sendbuf,cmd);

write(fd,sendbuf,strlen(sendbuf));

};

void down_file(int  sock,const char* args)

{

//下载文件

sendftp("TYPE I\r\n",sock);

int ftp_status=recvftp(sock);

if(ftp_status!=200){printf("ftp_status=%d\r\n",ftp_status);err_sys("类型错误

\r\n");};

sendftp("PASV\r\n",sock);

ftp_status=recvftp(sock);

if(ftp_status!=227)err_sys("进入被动模式错误\r\n");

struct sockaddr_in dest;

getaddrin(&dest);//通过被动模式,设置要连接的地址和端口

int fsock=socket(AF_INET,SOCK_STREAM,0);


if(fsock<=0)err_sys("socket2 创建错误\r\n");

if(connect(fsock,(struct sockaddr*)&dest,sizeof(dest))==-1)err_sys("无法连接

FTP 控制端口\r\n");

char tempbuf[512];

sprintf(tempbuf,"SIZE /%s\r\n",args);

sendftp(tempbuf,sock);

ftp_status=recvftp(sock);

if(ftp_status==213)

{

sprintf(tempbuf,"RETR  /%s\r\n",args);

sendftp(tempbuf,sock);

ftp_status=recvftp(sock);

if(ftp_status!=150)err_sys("RETR  错误!\r\n");

FILE * fp=fopen(args,"w+");

printf("%s\r\n",args);

if(fp==NULL)err_sys("nihaod");

while(1)

{

int n=read(fsock,buf,BUFSIZE);

if(n<=0)break;

fwrite(buf,sizeof(char),n,fp);

}

fflush(fp);

fclose(fp);

printf("文件下载完毕\r\n");

ftp_status=recvftp(sock);

if(ftp_status!=226)err_sysa(ftp_status,"文件传输错误226!\r\n");

}

else if(ftp_status==550)

{

printf("没有这个文件%s\r\n",args);

}

else err_sys("错误ftp  代码");

close(fsock);

};

void up_file(int  sock,const char* args)

{

FILE * fp=fopen(args,"r");

printf("%s\r\n",args);

if(fp==NULL){printf("无此文件\r\n");return;};


int flen;

fseek(fp,0,SEEK_END);

flen=ftell(fp);

fseek(fp,0,SEEK_SET);

//上传文件

sendftp("TYPE I\r\n",sock);

int ftp_status=recvftp(sock);

if(ftp_status!=200){printf("ftp_status=%d\r\n",ftp_status);err_sys("类型错误

\r\n");};

sendftp("PASV\r\n",sock);

ftp_status=recvftp(sock);

if(ftp_status!=227)err_sys("进入被动模式错误\r\n");

struct sockaddr_in dest;

getaddrin(&dest);//通过被动模式,设置要连接的地址和端口

int fsock=socket(AF_INET,SOCK_STREAM,0);

if(fsock<=0)err_sys("socket2 创建错误\r\n");

if(connect(fsock,(struct sockaddr*)&dest,sizeof(dest))==-1)err_sys("无法连接

FTP 控制端口\r\n");

char tempbuf[512];

sprintf(tempbuf,"STOR  /%s\r\n",args);

sendftp(tempbuf,sock);

ftp_status=recvftp(sock);

if(ftp_status!=150)err_sys("STOR  错误!\r\n");

FILE* sockfp=fdopen(fsock,"w");

if(sockfp==NULL)err_sys("sockfp  错误\r\n");

int i;

for(i=0;i<flen;i++)

fputc(fgetc(fp),sockfp);

fflush(sockfp);

fclose(sockfp);

fclose(fp);

ftp_status=recvftp(sock);

if(ftp_status!=226)err_sysa(ftp_status,"文件传输错误226!\r\n");

printf("文件上传完毕\r\n");

close(fsock);

};

void list_file(int  sock)

{


sendftp("TYPE I\r\n",sock);

int ftp_status=recvftp(sock);

if(ftp_status!=200){printf("ftp_status=%d\r\n",ftp_status);err_sys("类型错误

\r\n");};

sendftp("PASV\r\n",sock);

ftp_status=recvftp(sock);

if(ftp_status!=227)err_sys("进入被动模式错误\r\n");

struct sockaddr_in dest;

getaddrin(&dest);

int fsock=socket(AF_INET,SOCK_STREAM,0);

if(fsock<=0)err_sys("socket2 cuo wu\r\n");

if(connect(fsock,(struct sockaddr*)&dest,sizeof(dest))==-1)err_sys("wu  fa lianjian

dui fang\r\n");

sendftp("LIST\r\n",sock);

ftp_status=recvftp(sock);

if(ftp_status!=150)err_sys("打开文件错误!\r\n");

while(1)

{

int n=read(fsock,buf,BUFSIZE);

if(n<=0)break;

buf[n]=0;

printf("%s",buf);

}

ftp_status=recvftp(sock);

if(ftp_status!=226)err_sysa(ftp_status,"226  错误(250)!\r\n");

close(fsock);

}

int checkcode(const  int s,const int t)

{

if(s==t)

{

return 1;

}

else

{

printf("wrong code!\r\n");

}

return 0;

}

int recvftp(int  fd)


{

//返回ftp  代码,并且将所有字符串写在buf 

int n=read(fd,buf,BUFSIZE);

char stabuf[4];

buf[n]=0;

sscanf(buf,"%3s",stabuf);

int ftpcode=atoi(stabuf);

if(ftpcode<=0)err_sys("返回码错误\r\n");

return ftpcode;

}

void promt(const  char* s,char *cmd)

{

printf("%s",s);

fgets(cmd,32,stdin);

}

int main(int  argc,char* argv[])

{

char cmd[32];

int ftp_status=0;//ftp 服务器返回码

struct hostent *host;

if((host=gethostbyname(argv[1]))==NULL)

err_sys("Get hostanme error!\r\n");

int port=atoi(argv[2]);

if(argc==3&&port<0)

{

fprintf(stderr,"Usage:%s hostname  portnumber\r\n",argv[0]);

exit(-1);

}

/*生成套接字*/

int sock=socket(AF_INET,SOCK_STREAM,0);

if(sock<=0)err_sys("socket  error!\r\n");

/*FTP 服务器套接字地址*/

struct sockaddr_in  server_addr;

server_addr.sin_family=AF_INET;

server_addr.sin_port=htons(port);

server_addr.sin_addr=*((struct  in_addr*)host->h_addr);

/*连接服务器*/

int conret=connect(sock,(struct  sockaddr*)&server_addr,sizeof server_addr);

if(conret==-1)

{


fprintf(stderr,"connect error:%s\r\n",strerror(errno));

exit(-1);

}

/*获得FTP  返回码*/

ftp_status=recvftp(sock);

if(ftp_status!=220)err_sys("登录错误无法连接!220 \r\n");

printf("请输入[%s]用户名:(直接回车为默认的anonymous)

",inet_ntoa(server_addr.sin_addr));

fgets(cmd,sizeof(cmd),stdin);

//scanf(cmd,"%s");

cmd[strlen(cmd)-1]=0;//最后一个字符是0a,所以要去掉

if(strlen(cmd)!=0)

{

sprintf(sendbuf,"USER %s\r\n",cmd);

sendftp(sendbuf,sock);

ftp_status=recvftp(sock);

if(ftp_status!=331)err_sys("登录错误无法连接331\r\n");

terminal_echo_off(STDIN_FILENO);

printf("请输入密码: ");

fgets(cmd,sizeof(cmd),stdin);

terminal_echo_on(STDIN_FILENO);

cmd[strlen(cmd)-1]=0;//最后一个字符是0a,所以要去掉

sprintf(sendbuf,"PASS  %s\r\n",cmd);

sendftp(sendbuf,sock);

ftp_status=recvftp(sock);

if(ftp_status!=230)err_sys("密码错误230\r\n");

}

else

{

sendftp("USER anonymous\r\n",sock);

ftp_status=recvftp(sock);

sendftp("PASS IEUSER@\r\n",sock);

ftp_status=recvftp(sock);

if(ftp_status!=230)err_sys("不支持匿名登录\r\n");

}

printf("建立和ftp  服务器的连接\r\n");

/*进入被动模式*/

char totalcmd[512];


本文转自陈仲阳0 51CTO博客,原
char args[256];

while(1)

{

while(1)

{

promt("请输入命令:",totalcmd);

sscanf(totalcmd,"%s%s",cmd,args);

if(cmd==NULL){printf("输入命令错误,重新输入命令");continue;};

if(strcasecmp(cmd,"quit")==0)

{

printf("退出程序!\r\n");

close(sock);

exit(0);

}

break;

}

if(strcasecmp(cmd,"ls")==0||strcasecmp(cmd,"dir")==0)

list_file(sock);

if(strcasecmp(cmd,"GET")==0)down_file(sock,args);

if(strcasecmp(cmd,"PUT")==0)up_file(sock,args);

本文转自陈仲阳0 51CTO博客,原文链接:http://blog.51cto.com/wolfword/1240349



相关文章
|
7月前
|
数据安全/隐私保护 网络架构 内存技术
H3C配置管理实验--ftp
H3C配置管理实验--ftp
关于 虚拟机交叉编译目标机程序,使用filezilla的ftp方式传输到板子上没问题,后来同样环境传入应用运行宕机 的解决方法
关于 虚拟机交叉编译目标机程序,使用filezilla的ftp方式传输到板子上没问题,后来同样环境传入应用运行宕机 的解决方法
关于 虚拟机交叉编译目标机程序,使用filezilla的ftp方式传输到板子上没问题,后来同样环境传入应用运行宕机 的解决方法
|
安全 Linux Windows
FTP服务器端程序分类
FTP服务器端程序有很多种,其中最常见的是vsftpd,顾名思义就是very secure ftp daemon(非常安全的ftp进程)。 除此之外还有比vsftpd功能更强大的几种ftp程序: ① wu-ftpd:ftp界的鼻祖,但是未采用模块化设计,不安全 ② proftpd ③...
788 0
|
网络安全 C# 数据安全/隐私保护
【转载】.NET 2.0下简单的FTP访问程序
.NET 2.0下简单的FTP访问程序[简介] 也许大家也不想总依赖着第三方FTP软件,值得高兴的是,本文将给你开发出一套免费的来。尽管,本文中的代码没有设计成可重用性很高的库,不过确实是一个简单的可以重复使用部分代码的程序。
740 0