linux 下简单的ftp客户端程序

该ftp的客服端是在linux下面写,涉及的东西也比较简单,如前ftp的简单介绍,知道ftp主要的工作流程架构,套接字的创建,还有就是字符串和字符的处理。使用的函数都是比较简单平常易见的,写的时候感觉有将以前学的函数从新巩固一遍。这个简易的ftp客服端只是完成了基本的工作,还有许多的问题有待解决。如:目前最大的问题是使用pasv(被动模式)连接的时候,某些情况下会出现运行错误或同一个运行程序中使用两次pasv的被动连接就是出现运行错误而退出。注意:ftp的测试最好是用linux平台下搭建,连接编码不同ftp会出现错误。

转载请标明出处
代码如下:
/*************************
方便测试ftp:172.16.120.77
author:fengbo
*************************/
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<netinet/in.h>
#include<unistd.h>
#include<netdb.h>
#include<curses.h>
#defineMAXSIZE1024
#definebuff512

char*data_port;
intport;
char*p,*ptr;

intc_sockfd,d_sockfd;
intread_status,write_status;
//////////////////////////
charread_buf[200];//控制端口缓存
charread_d_buf[512];//数据端口缓存
charsend_buf[100];
charcommand[40];
charcom_input[15];//输入字符缓存
charpara_input[20];

structsockaddr_inserveraddr_d;
///////////////////////////////
staticvoiddisplay_order();//命令提示
staticvoidftp_d_port();//pasv获得端口
staticvoidftp_c_socket(intargc1,char**argv1);//命令端口创建
staticvoidftp_d_socket(char*argv2);//数据端口创建
staticvoidset_pasv(char*argv3);//设置被动模式
///////////////////////////////
staticvoidftp_c_socket(intargc1,char**argv1){

intret,i,com_len=0;
intcom_i=0,para_i=0;
into_file,r_file,w_file;//文件的描述符
char*com_status,*para_status;
structsockaddr_inserveraddr_c;//网络字节序序存的结构体变量
socklen_tsock_size;

chardir_name[15];//dir的当前目录
charfile_name[20];
charusername[20];
charpassword[20];
charcatalog[20];//需要cd的目录
chardownload_file[20];
charmkdir_catalog[20];//创建目录

/////////////////////////
sock_size=sizeof(structsockaddr);
serveraddr_c.sin_family=AF_INET;
serveraddr_c.sin_port=htons(21);
serveraddr_c.sin_addr.s_addr=inet_addr(argv1[1]);
memset(&(serveraddr_c.sin_zero),0,8);
c_sockfd=socket(AF_INET,SOCK_STREAM,0);//创建sock套接字
if(c_sockfd<0){

perror("creatsocketerror!
");
return;
}

ret=connect(c_sockfd,(structsockaddr*)&serveraddr_c,sock_size);
if(ret<0){

perror("connecterror!
");
return;
}
printf("connecttheserverFTPsuccessfully!
");
read_status=read(c_sockfd,read_buf,sizeof(read_buf));//读取ftp的链接欢迎信息
if(read_status==-1){
perror("errortogaintheftpwelconmeinformation!
");
}
printf("theinformation:%s
",read_buf);
/////////////////login//////////////////////////
printf("--------------------------pleasetologin--------------------------
");
printf("
");
printf("***username:");
scanf("%s",username);
getchar();
printf("
");
printf("***password:");
scanf("%s",password);

getchar();
printf("
");
printf("--------------------------------------------------------------------
");

///////////////username//////////////////////////
memset(read_buf,0,sizeof(read_buf));
sprintf(send_buf,"USER%s
",username);

write_status=write(c_sockfd,send_buf,strlen(send_buf));
if(write_status==-1){
perror("failuretosendtheusername
");
}
read_status=read(c_sockfd,read_buf,sizeof(read_buf));//读取ftp用户链接的返回信息
if(read_status==-1){
perror("errortogaintheftpinformation!
");
}
if(atoi(read_buf)!=331){
printf("errortologintheftp'username'
");
}
printf("theinformation:%s
",read_buf);

/////////////////password//////////////////////////
memset(send_buf,0,sizeof(send_buf));
memset(read_buf,0,sizeof(read_buf));
sprintf(send_buf,"PASS%s
",password);

write_status=write(c_sockfd,send_buf,strlen(send_buf));
if(write_status==-1){
perror("failuretosendthepassword
");
}
read_status=read(c_sockfd,read_buf,sizeof(read_buf));//读取ftp用户链接的返回信息
if(read_status==-1){
perror("errortogaintheftpinformation!
");
}
if(atoi(read_buf)!=230){
printf("errortologintheftp'password'
");
exit(-1);
}
printf("theinformation:%s
",read_buf);

///////////////////设置PASV模式/////////////////////
//set_pasv();
///////////////获取端口函数/////////////////////////
//ftp_d_port();
////////////////////////////发送数据端口请求/////////
//ftp_d_socket(argv1[1]);
//////////////////displaythecommand////////////////
display_order();
///////////////////////////命令控制//////////////////

while(1){
printf("%sftp>",username);
scanf("%s",command);//从键盘获取命令和参数
getchar();
com_len=strlen(command);//长度
if(com_len>5){
com_status=strstr(command,"-");//取命令和参数分界点
while(command[com_i]!=*com_status){
com_input[com_i]=command[com_i];
com_i++;
}//获取到命令
//printf("%s
",com_input);
com_status++;
for(para_i=0;para_i<=(com_len-com_i-1);para_i++){
para_input[para_i]=*com_status;
com_status++;
}//获取到参数
//printf("%s
",para_input);
com_i=0;
}
else{
strcpy(com_input,command);
}
//////////////////////大小写转换///////////////////
/*for(i=0;i<strlen(command);i++){

if(strcmp("command[i]","a")>=0){
command[i]=(command[i]-32);
}

}*/
set_pasv(argv1[1]);
if(strcmp(com_input,"PWD")==0){
///////////////////////当前路径/////////////////////////////
memset(read_buf,0,sizeof(read_buf));
memset(send_buf,0,sizeof(send_buf));

sprintf(send_buf,"PWD
");
write_status=write(c_sockfd,send_buf,strlen(send_buf));//命令写入控制套接连接
if(write_status==-1){
perror("failuretosendtheinformationfor'PWD'
");
}
read_status=read(c_sockfd,read_buf,sizeof(read_buf));//读取ftp用户链接的返回信息
if(read_status==-1){
perror("errortogaintheftpinformation!
");
}
//if(atoi(read_buf)!=257){
//printf("errortosetthePASVmodel
");
//}
printf("%s
",read_buf);
}
elseif(strcmp(com_input,"DIR")==0){
///////////////////////显示目录文件///////////////////

memset(read_buf,0,sizeof(read_buf));
memset(send_buf,0,sizeof(send_buf));
strcpy(dir_name,para_input);

sprintf(send_buf,"LIST%s
",dir_name);
write_status=write(c_sockfd,send_buf,strlen(send_buf));//命令写入控制套接连接
if(write_status==-1){
perror("failuretosendtheinformationfor'LIST'
");
}
read_status=read(c_sockfd,read_buf,sizeof(read_buf));//读取ftp用户链接的返回信息
if(read_status==-1){
perror("errortogaintheftpinformation!
");
}
printf("%s
",read_buf);
//if(atoi(read_buf)!=){

//printf("errortosetthePASVmodel
");
//}
memset(read_d_buf,0,sizeof(read_d_buf));
while(read(d_sockfd,read_d_buf,sizeof(read_d_buf))>0){

printf("%s",read_d_buf);
memset(read_d_buf,0,sizeof(read_d_buf));
}
close(d_sockfd);
memset(&serveraddr_d,0,sizeof(serveraddr_d));
}
elseif(strcmp(com_input,"QUIT")==0){
/////////////////////////////退出/////////////////////////
close(d_sockfd);
printf("数据端口已关闭
");
memset(read_buf,0,sizeof(read_buf));
memset(send_buf,0,sizeof(send_buf));

sprintf(send_buf,"QUIT
");
write_status=write(c_sockfd,send_buf,strlen(send_buf));//命令写入控制套接连接
if(write_status==-1){
perror("failuretosendtheinformationfor'RETR'
");
}
read_status=read(c_sockfd,read_buf,sizeof(read_buf));//读取ftp用户链接的返回信息
if(read_status==-1){
perror("errortogaintheftpinformation!
");
}
//if(atoi(read_buf)!=257){
//printf("errortosetthePASVmodel
");
//}
printf("%s
",read_buf);
break;
}
elseif(strcmp(com_input,"GET")==0){

/////////////////////////////下载文件/////////////////////

memset(read_buf,0,sizeof(read_buf));
memset(send_buf,0,sizeof(send_buf));
memset(read_d_buf,0,sizeof(read_d_buf));

strcpy(download_file,para_input);
sprintf(send_buf,"RETR%s
",download_file);
write_status=write(c_sockfd,send_buf,strlen(send_buf));
if(write_status==-1){
perror("failuretosendtheinformationfor'RETR'
");
}
read_status=read(c_sockfd,read_buf,sizeof(read_buf));//读取ftp用户链接的返回信息
if(read_status==-1){
perror("errortogaintheftpinformation!
");
}
//if(atoi(read_buf)!=257){
//printf("errortosetthePASVmodel
");
//}
printf("%s
",read_buf);

o_file=open(download_file,O_WRONLY|O_CREAT|O_TRUNC,0644);//创建文件客服端
if(o_file==-1){
printf("errortoopenthe%s
",file_name);
exit(-1);
}

while((r_file=read(d_sockfd,read_d_buf,sizeof(read_d_buf)))>0){

write(o_file,read_d_buf,r_file);//写入文件
memset(read_d_buf,0,sizeof(read_d_buf));
}
printf("transportthefilesuccessfuly!
");
close(o_file);
close(d_sockfd);
memset(&serveraddr_d,0,sizeof(serveraddr_d));
}
elseif(strcmp(com_input,"CD")==0){
///////////////////////跳转目录/////////////////////////////
memset(read_buf,0,sizeof(read_buf));
memset(send_buf,0,sizeof(send_buf));

strcpy(catalog,para_input);
sprintf(send_buf,"CWD%s
",catalog);
write_status=write(c_sockfd,send_buf,strlen(send_buf));//命令写入控制套接连接
if(write_status==-1){
perror("failuretosendtheinformationfor'DELE'
");
}
read_status=read(c_sockfd,read_buf,sizeof(read_buf));//读取ftp用户链接的返回信息
if(read_status==-1){
perror("errortogaintheftpinformation!
");
}
//if(atoi(read_buf)!=257){
//printf("errortosetthePASVmodel
");
//}
printf("%s
",read_buf);
}
elseif(strcmp(com_input,"DEL")==0){
///////////////////////删除文件/////////////////////////////
memset(read_buf,0,sizeof(read_buf));
memset(send_buf,0,sizeof(send_buf));

strcpy(file_name,para_input);
sprintf(send_buf,"DELE%s
",file_name);
write_status=write(c_sockfd,send_buf,strlen(send_buf));//命令写入控制套接连接
if(write_status==-1){
perror("failuretosendtheinformationfor'DELE'
");
}
read_status=read(c_sockfd,read_buf,sizeof(read_buf));//读取ftp用户链接的返回信息
if(read_status==-1){
perror("errortogaintheftpinformation!
");
}
//if(atoi(read_buf)!=257){
//printf("errortosetthePASVmodel
");
//}
printf("%s
",read_buf);
}
elseif(strcmp(com_input,"MKDIR")==0){
///////////////////////创建目录/////////////////////////////
memset(read_buf,0,sizeof(read_buf));
memset(send_buf,0,sizeof(send_buf));

strcpy(mkdir_catalog,para_input);
sprintf(send_buf,"MKD%s
",mkdir_catalog);
write_status=write(c_sockfd,send_buf,strlen(send_buf));//命令写入控制套接连接
if(write_status==-1){
perror("failuretosendtheinformationfor'DELE'
");
}
read_status=read(c_sockfd,read_buf,sizeof(read_buf));//读取ftp用户链接的返回信息
if(read_status==-1){
perror("errortogaintheftpinformation!
");
}
//if(atoi(read_buf)!=257){
//printf("errortosetthePASVmodel
");
//}
printf("%s
",read_buf);
}
else{
printf("***************thecommanderror!****************
");
display_order();//显示命令
}
}


}
//////////////////////////PASV被动模式设置/////////////////////////////////
staticvoidset_pasv(char*argv3){
memset(send_buf,0,sizeof(send_buf));
memset(read_buf,0,sizeof(read_buf));
sprintf(send_buf,"PASV
");
write_status=write(c_sockfd,send_buf,strlen(send_buf));
if(write_status==-1){
perror("failuretosendtheinformationfor'PASV'
");
}
read_status=read(c_sockfd,read_buf,sizeof(read_buf));//读取ftp用户链接的返回信息
if(read_status==-1){
perror("errortogaintheftpinformation!
");
}
printf("%s",read_buf);
if(atoi(read_buf)!=227){
printf("errortosetthePASVmodel
");
}
ftp_d_port();//获取端口
ftp_d_socket(argv3);//数据套接字创建

}
/////////////////////////获取端口函数实现///////////////////////////////////
staticvoidftp_d_port(){

char*port_status1,*port_status2,*index,extend,extend_1;
intport_temp1[4],port_temp2[4];//当时出现错误,变量为int型
intport_i=0,port_ii=0,count,count_i,count_ii;
inttemp=0,temp1=0,temp2,port_point;

port_status1=strstr(read_buf,"(");//取“(”里面的
port_status1++;
for(port_point=0;port_point<4;port_point++){//取第4个逗号位置
port_status2=strstr(port_status1,",");
port_status2++;
port_status1=port_status2;
}
port_status2=strstr(port_status1,",");//取第5个逗号位置
while(port_status1!=port_status2){
extend=*port_status1;
port_temp1[port_i]=(int)(extend-48);//获取5~6逗号间数据
port_i++;
port_status1++;
}
port_status2++;
port_status1=port_status2;
port_status2=strstr(port_status1,")");//取")"的位置
while(port_status1!=port_status2){
extend_1=*port_status1;
port_temp2[port_ii]=(extend_1-48);//获得")"之前的数据
port_ii++;
port_status1++;
}
count_i=port_i;
for(count=0;count<port_i;count++){
if(count_i==3){
count_ii=100;
}
elseif(count_i==2){
count_ii=10;
}
elseif(count_i==1){
count_ii=1;
}
temp=temp+port_temp1[count]*count_ii;//计算p1
count_i--;
}
count_i=port_ii;
for(count=0;count<port_ii;count++){
if(count_i==3){
count_ii=100;
}
elseif(count_i==2){
count_ii=10;
}
elseif(count_i==1){
count_ii=1;
}
temp1=temp1+port_temp2[count]*count_ii;//计算p2
count_i--;
}
port=temp*256+temp1;//p1*256+p2
printf("theinformation:%s
",read_buf);
}
//////////////////////////命令提示////////////////////////////////////////
staticvoiddisplay_order(){
printf("****************************************************
");
printf("youcaninputtheCommand:
");
printf("DIR,PWD,GET,PUT,QUIT,CD,DEL,MKDIR
");
printf("attention:命令和参数间用'-'分开
");
printf("****************************************************
");

}
///////////////////////////数据传送端口////////////////////////////////////

staticvoidftp_d_socket(char*argv2){

intret_d;
//structsockaddr_inserveraddr_d;
socklen_tsock_d_size;

sock_d_size=sizeof(structsockaddr);
serveraddr_d.sin_family=AF_INET;
serveraddr_d.sin_port=htons(port);
serveraddr_d.sin_addr.s_addr=inet_addr(argv2);
memset(&(serveraddr_d.sin_zero),0,8);
d_sockfd=socket(AF_INET,SOCK_STREAM,0);
if(d_sockfd<0){
perror("creatdata_socketerror
");
exit(-1);
}
ret_d=connect(d_sockfd,(structsockaddr*)&serveraddr_d,sock_d_size);
if(ret_d<0){
perror("data_connecterror!
");
exit(-1);
}
printf("connecttheFTPdataportsuccessfully!
");
}

intmain(intargc,char**argv){

ftp_c_socket(argc,argv);
return0;
}
http://xfb2020.blog.163.com/blog/static/198496112201317113750789/
原文地址:https://www.cnblogs.com/pengkunfan/p/3588699.html