首页 > 代码库 > linux C 实现FTP客户端
linux C 实现FTP客户端
****************************************************************************************
我已参加2014“博客之星的”评选,觉得我的文章对您有帮助的,请投上您宝贵的一票
****************************************************************************************
参考资料:
1、使用 Socket 通信实现 FTP 客户端程序
#include<stdio.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<string.h>
#include<strings.h>
#include<unistd.h>
#include<netinet/in.h>
#include<netdb.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#define SERV_PORT 21
#define MAXSIZE 1024
#define SA struct sockaddr
static int control_sockfd;
int npsupport;
int login_yes;
int f;//f=0时为默认文件结构
int login();
void ftp_list(int control_sockfd);
void zeromery(char *a,int len);
void ftp_pwd(int control_sockfd);
void ftp_changdir(char dir[],int control_sockfd);
void ftp_quit(int control_sockfd);
void ftp_creat_mkd(char *path,int control_sockfd);
void ftp_back(int control_sockfd);
void ftp_stru(int control_sockfd);
void ftp_rest(int control_sockfd);
int ftp_download(int control_sockfd);
char *itoa(int value, char *string, int radix);
int main(int argc,char **argv)
{
printf("ftp>");
char command[MAXSIZE];
char*cmd;
scanf("%s",command);
cmd=command;
while(*(cmd)==‘ ‘)
cmd++;
if(strncmp(cmd,"login",5)==0)
{
login();
if(login_yes==1)
{
while(1)
{
comm:
sleep(1);
printf("ftp>");
zeromery(command,1024);
scanf("%s",command);
cmd=command;
while(*(cmd)==‘ ‘)
cmd++;
if(strncmp(cmd,"pasv",4)==0)
{
ftp_list(control_sockfd);
}
if(strncmp(cmd,"port",4)==0)
{
ftp_list(control_sockfd);
}
if(strncmp(cmd,"list",4)==0)
{
ftp_pwd(control_sockfd);
ftp_list(control_sockfd);
}
if(strncmp(cmd,"pwd",3)==0)
{
ftp_pwd(control_sockfd);
}
if(strncmp(cmd,"mkdir",5)==0)
{
char path[60];
zeromery(path,60);
printf("创建的路径名: ");
scanf("%s",path);
printf("s/n",path);
ftp_creat_mkd(path,control_sockfd);
}
if(strncmp(cmd,"back",4)==0)
{
ftp_back(control_sockfd);
ftp_pwd(control_sockfd);
}
if(strncmp(cmd,"cd",2)==0)
{
int i;
char path[60];
zeromery(path,60);
printf("要到的路径:");
scanf("%s",path);
printf("%s/n",path);
ftp_changdir(path,control_sockfd);
}
if(strncmp(cmd,"get",3)==0)
{
ftp_pwd(control_sockfd);
ftp_download(control_sockfd);
}
if(strncmp(cmd,"up",3)==0)
{
ftp_pwd(control_sockfd);
ftp_up(control_sockfd);
}
if(strncmp(cmd,"quit",4)==0)
{
printf("bye^_^/n");
close(control_sockfd);
break;
}
printf("支持 list,pwd,mkdir,back,cd,up,get/n");
}
}
else if(login_yes==0)
{
int i;//不成功登录下最多还有两次机会,如果不能在两次登录,则,关闭链接。
printf("Can not login vsftpd");
for(i=2;i>0;i--)
{
printf("你还有 %d 登录机会/n",i);
login();
if(login_yes==1)
{
goto comm;
}
}
if(i==0)
{
printf("你不能在登录!/n");
close(control_sockfd);
}
}
else if (strncmp(cmd,"quit",4)==0)
{
ftp_quit(control_sockfd);
close(control_sockfd);
}
}
return 0;
}
int login()
{
//初始化端口信息
struct sockaddr_in serv_addr;
char senddate,recvdate;
char sendline[MAXSIZE],recvline[MAXSIZE];
struct hostent *host;
//获取hostent中相关参数
char name[MAXSIZE],password[MAXSIZE];
printf("please enter the hostname/n");
printf("ftp-> ");
scanf("%s",name);
host=gethostbyname(name);
if(host==NULL)
{
printf("get host by name is error!/n");
login_yes=0;
}
else
{
//创建socket
control_sockfd=socket(AF_INET,SOCK_STREAM,0);
if(control_sockfd<0)
{
printf("socket is error/n");
login_yes=0;
}
//设置sockaddr_in 结构体中的相关参数
bzero(&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERV_PORT);
serv_addr.sin_addr.s_addr=INADDR_ANY;
//调用connect函数发起连接
char addr[MAXSIZE];
if((connect(control_sockfd,(SA*)&serv_addr,sizeof(serv_addr)))<0)
{
printf("connect is error/n");
login_yes=0;
}
printf("connect to %s/n",inet_ntop(AF_INET,host->h_addr,addr,1024));
recvdate=recv(control_sockfd,recvline,sizeof(recvline),0);
if(recvdate==-1)
{
printf("recvdate is connect error/n");
login_yes=0;
}
else if(strncmp(recvline,"220",3)==0)
{
printf("connect success,pelase enter username/n");
login_yes=1;
}
else
{
printf("220 connect is error!");
login_yes=0;
}
//ftp用户登录主体部分
int sendbytes,recvbytes;
zeromery(name,1024);
zeromery(password,1024);
zeromery(recvline,1024);
zeromery(sendline,1024);
printf("ftp-> ");
scanf("%s",name);//可以支持匿名登录vsftpd
strcat(sendline,"USER ");
strcat(sendline,name);
strcat(sendline,"/r/n");
printf("--->%s/n",sendline);
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes==-1)
{
printf("send is wrong/n");
login_yes=0;
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(strncmp(recvline,"331",3)==0)
{
printf("331 please specify the password./n");
}
else
{
printf("recv date is error./n");
login_yes=0;
}
zeromery(sendline,1024);
zeromery(recvline,1024);
printf("ftp-> ");
scanf("%s",password);
strcat(sendline,"PASS ");
strcat(sendline,password);
strcat(sendline,"/r/n");
printf("--->%s/n",sendline);
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes==-1)
{
printf("pass send is error/n");
login_yes=0;
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(strncmp(recvline,"230",3)==0)
{
printf("login success!/n");
login_yes=1;
}
else
{
printf("pass recv is error/n");
login_yes=0;
}
//支持断点续传
zeromery(sendline,1024);
zeromery(recvline,1024);
strcat(sendline,"REST ");
strcat(sendline,"0");
strcat(sendline,"/r/n");
printf("--->%s/n",sendline);
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes==-1)
{
printf("rest send is error!/n");
login_yes=0;
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(recvbytes==-1)
{
printf("rest recv date is error./n");
login_yes=0;
}
if(strncmp(recvline,"350 Restart position accepted (0).",34)==0)
{
npsupport=1;
printf("support 断点续传/n");
login_yes=1;
}
else
{
npsupport=0;
printf("not support 断点续传/n");
login_yes=0;
}
//获取服务器版本信息
zeromery(recvline,1024);
zeromery(sendline,1024);
strcat(sendline,"SYST");
strcat(sendline,"/r/n");
printf("--->%s/n",sendline);
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes==-1)
{
printf("syst send is error/n");
login_yes=0;
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(recvbytes==-1)
{
printf("syst recv is error/n");
login_yes=0;
}
if(strncmp(recvline,"215 UNIX Type: L8",17)==0)
{
printf("%s",recvline);
login_yes=1;
}
else
{
printf("syst recv connectin is error/n");
login_yes=0;
}
}
return login_yes;
}
//数组初始化
void zeromery(char *a,int len)
{
int i;
len=sizeof(a);
for(i=0;i<len;i++)
{
a[i]=0;
}
}
//quit函数,control_sockfd,通过实参传递
void ftp_quit(int control_sockfd )
{
char sendline[1024];
char recvline[1024];
int recvbytes;
int sendbytes;
zeromery(sendline,1024);
zeromery(recvline,1024);
strcat(sendline,"QUIT");
strcat(sendline,"/r/n");
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("quit send is error!/n");
exit(1);
}
recvbytes=recv(control_sockfd,recvline,strlen(recvline),0);
if(strncmp(recvline,"221",3)==0)
{
printf("221 bye!^_^");
exit(1);
}
else
{
printf("quit recv is error!/n");
exit(1);
}
}
//mkd,在所在路径中创建目录 函数
void ftp_creat_mkd(char *path,int control_sockfd)
{
char sendline[1024];
char recvline[1024];
zeromery(sendline,1024);
zeromery(recvline,1024);
int recvbytes,sendbytes;
int issuccess;
strcat(sendline,"MKD ");
strcat(sendline,path);
strcat(sendline,"/r/n");
printf("%s/n",sendline);
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("mkd send is error!");
exit(1);
}
recvbytes=recv(control_sockfd,recvline,strlen(recvline),0);
if(strncmp(recvline,"257",3)==0)
{
issuccess=1;
}
else
{
issuccess=0;
}
}
//改变目录函数chdir
void ftp_changdir(char *dir,int control_sockfd)
{
char sendline[1024];
char recvline[1024];
int recvbytes,sendbytes;
zeromery(sendline,1024);
zeromery(recvline,1024);
strcat(sendline,"CWD ");
strcat(sendline,dir);
strcat(sendline,"/r/n");
printf("%s/n",sendline);
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("cwd send is error!/n");
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(recvbytes<0)
{
printf("cwd recv is error!/n");
}
if(strncmp(recvline,"250",3)==0)
{
char buf[55];
snprintf(buf,39,">>> %s/n",recvline);
printf("%s/n",buf);
}
else
{
printf("cwd chdir is error!/n");
exit(1);
}
}
//pwd 命令函数
//在应答中返回当前工作目录,“pwd”+/r/n
void ftp_pwd(int control_sockfd)
{
int recvbytes,sendbytes;
char sendline[1024],recvline[1024];
zeromery(sendline,1024);
zeromery(recvline,1024);
strcat(sendline,"PWD");
strcat(sendline,"/r/n");
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("pwd,send is error/n");
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(strncmp(recvline,"257",3)==0)
{
int i=0;
char *ptr;
char currendir[1024];
zeromery(currendir,1024);
ptr=recvline+5;
while(*(ptr)!=‘"‘)
{
currendir[i++]=*(ptr);
ptr++;
}
currendir[i]=‘/0‘;
printf("current directory is:%s/n",currendir);
}
else
{
printf("pwd,recv is error!/n");
}
}
//获取服务器文件列表
//list命令,是数据通道,通过的是21端口。the function ‘s struct is "the data //transport mode"(ascii or b) puls "the data mode to transport"(pasv or port//) puls "the list command"
void ftp_list(int control_sockfd)
{
int pasv_or_port;// 定义the ftp协议的两种不同工作mode
int recvbytes,sendbytes;
char sendline[1024],recvline[1024];
struct sockaddr_in serv_addr;
int i,j;
int flag=0;
int data_sockfd;
//用户来选择pasv 或者是 port mode(默认的是pasv模式)
char selectdata_mode_tran[1024];
zeromery(selectdata_mode_tran,1024);
zeromery(sendline,1024);
zeromery(recvline,1024);
//printf("ftp->ftp协议工作方式选择(pasv or port)/n");
//printf("ftp->");
// scanf("%s",selectdata_mode_tran);
//if(strncmp(selectdata_mode_tran,"pasv",4)==0)
//{
pasv_or_port=0;
// }
// if(strncmp(selectdata_mode_tran,"port",4)==0)
// {
// pasv_or_port=1;
// }
//pasv mode
if(pasv_or_port==0)
{
strcat(sendline,"PASV");
strcat(sendline,"/r/n");
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("pasv send is error!/n");
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(recvbytes<0)
{
printf("pasv recv is error!/n");
}
if(strncmp(recvline,"227",3)==0)
{
printf("%s/n",recvline);
}
else
{
printf("pasv recv is error!/n");
}
//处理ftp server 端口
char *ptr1,*ptr2;
char num[1024];
zeromery(num,1024);
//取低位字节
ptr1=recvline+strlen(recvline);
while(*(ptr1)!=‘)‘)
{
ptr1--;
}
ptr2=ptr1;
while(*(ptr2)!=‘,‘)
ptr2--;
strncpy(num,ptr2+1,ptr1-ptr2-1);
i=atoi(num);//将字符串转换成整数
//取高位字节
zeromery(num,1024);
ptr1=ptr2;
ptr2--;
while(*(ptr2)!=‘,‘)
ptr2--;
strncpy(num,ptr2+1,ptr1-ptr2-1);
j=atoi(num);
//初始化服务器数据连接时的端口信息
int data_serviceport;
data_serviceport=j*256+i;
data_sockfd=socket(AF_INET,SOCK_STREAM,0);
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=INADDR_ANY;
serv_addr.sin_port=htons(data_serviceport);
if(connect(data_sockfd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr))==-1)
{
printf("pasv data connect is error!/n");
}
}
//port mode
if(pasv_or_port==1)
{
data_sockfd=socket(AF_INET,SOCK_STREAM,0);
if(data_sockfd<0)
{
printf("创建数据端口连接失败!/n");
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=INADDR_ANY;
serv_addr.sin_port=htons(SERV_PORT);
int ret;
int addrlen;
ret=sizeof(struct sockaddr_in);
getsockname(data_sockfd,(SA*)&serv_addr,&ret);
//处理port 后面要带的参数
char ip[1024];
int i,j;
char data[1024];
zeromery(ip,1024);
zeromery(data,1024);
inet_ntop(AF_INET,&(serv_addr.sin_addr),ip,sizeof(ip));
printf("%s/n",ip);
i=data_sockfd/256;
j=data_sockfd%256;
//将点分十进制的点转换为逗号。
char *ptr1;
ptr1=ip;
while(*(ptr1)!=‘/0‘)
{
if(*(ptr1)==‘.‘)
{
*(ptr1)=‘,‘;
}
ptr1++;
}
strcat(sendline,"PORT ");
strcat(sendline,ip);
strcat(sendline,",");
strcat(sendline,itoa(i,data,10));
strcat(sendline,",");
strcat(sendline,itoa(j,data,10));
strcat(sendline,"/r/n");
printf("--->%s/n",sendline);
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("port send is error!/n");
exit(1);
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(strncmp(recvline,"200",3)==0)
{
printf("%s/n",recvline);
}
else
{
printf("port recv is error!/n");
}
}
//type
zeromery(recvline,1024);
zeromery(sendline,1024);
strcat(sendline,"TYPE ");
strcat(sendline,"I");
strcat(sendline,"/r/n");
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf(" type send is error!/n");
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(strncmp(recvline,"200",3)==0)
{
printf("使用二进制传输数据/n");
}
else
{
printf("type recv is error!/n");
}
//list
zeromery(sendline,1024);
zeromery(recvline,1024);
strcat(sendline,"LIST");
strcat(sendline,"/r/n");
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("list send is error!/n");
}
recvdata:
sleep(1);
recvbytes=recv(data_sockfd,recvline,sizeof(recvline),0);
if(recvbytes<0)
{
close(data_sockfd);
goto ending;
}
printf("%s",recvline);
if(flag==0)
{
zeromery(recvline,1024);
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(strncmp(recvline,"226",3)!=0)
{
flag=1;
goto recvdata;
}
}
ending:
if(flag!=1)
{
zeromery(recvline,1024);
}
close(data_sockfd);
}
//itoa 函数的实现(整数转换成字符串)
char *itoa(int value, char *string, int radix)
{
char tmp[33];
char *tp = tmp;
int i;
unsigned v;
int sign;
char *sp;
sign = (radix == 10 && value < 0);
if (sign)
v = -value;
else
v = (unsigned)value;
while (v || tp == tmp)
{
i = v % radix;
v = v / radix;
if (i < 10)
*tp++ = i+‘0‘;
else
*tp++ = i + ‘a‘ - 10;
}
if (string == 0)
string = (char *)malloc((tp-tmp)+sign+1);
sp = string;
if (sign)
*sp++ = ‘-‘;
while (tp > tmp)
*sp++ = *--tp;
*sp = 0;
return string;
}
//back 返回上一级函数,相当于cd /;
void ftp_back(int control_sockfd)
{
char sendline[1024],recvline[1024];
int recvbytes,sendbytes;
zeromery(sendline,1024);
zeromery(recvline,1024);
strcat(sendline,"CDUP");
strcat(sendline,"/r/n");
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("cdup send is error !/n");
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(recvbytes<0)
{
printf("cdup recv is error !/n");
}
if(strncmp(recvline,"250",3)==0)
{
printf("请求的文件操作已经成功/n");
}
}
//stru命令的实现
void ftp_stru(int control_sockfd)
{
int recvbytes,sendbytes;
char sendline[1024],recvline[1024];
zeromery(sendline,1024);
zeromery(recvline,1024);
strcat(sendline,"STRU");
strcat(sendline,"F");
strcat(sendline,"/r/n");
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("stru send is error!/n");
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(recvbytes<0)
{
printf("stru recv is error!/n");
}
if(strncmp(recvline,"200",3)==0)
{
f=0;
}
}
//断点函数的支持
void ftp_rest(int control_sockfd)
{
int recvbytes,sendbytes;
char sendline[1024],recvline[1024];
zeromery(sendline,1024);
zeromery(recvline,1024);
strcat(sendline,"REST ");
strcat(sendline,"500");
strcat(sendline,"/r/n");
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("stru send is error!/n");
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(recvbytes<0)
{
printf("stru recv is error!/n");
}
if(strncmp(recvline,"350",3)==0)
{
printf("%s/n",recvline);
}
}
//下载的实现函数
int ftp_download(int control_sockfd)
{
int pasv_or_port;// 定义the ftp协议的两种不同工作mode
int recvbytes,sendbytes;
char sendline[1024],recvline[1024];
struct sockaddr_in serv_addr;
FILE *fd;
int i,j;
int data_sockfd;
//rest
ftp_rest(control_sockfd);
//type
zeromery(recvline,1024);
zeromery(sendline,1024);
strcat(sendline,"TYPE ");
strcat(sendline,"I");
strcat(sendline,"/r/n");
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf(" type send is error!/n");
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(strncmp(recvline,"200",3)==0)
{
printf("使用二进制传输数据/n");
}
else
{
printf("type recv is error!/n");
}
if(npsupport==1)
{
//open the file
int size;
char localpathname[60];//预打开的文件路径字符串
int flags;
char pathname[60];
unsigned int mode;
//用户来选择pasv 或者是 port mode
char selectdata_mode_tran[1024];
zeromery(selectdata_mode_tran,1024);
zeromery(sendline,1024);
zeromery(recvline,1024);
pasv_or_port=0;//(默认是pasv模式)
//pasv mode
if(pasv_or_port==0)
{
strcat(sendline,"PASV");
strcat(sendline,"/r/n");
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("pasv send is error!/n");
}
zeromery(recvline,1024);
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(recvbytes<0)
{
printf("pasv recv is error!/n");
}
if(strncmp(recvline,"227",3)==0)
{
char buf[55];
snprintf(buf,51,">>> %s/n",recvline);
printf("%s/n",buf);
}
else
{
printf("pasv recv is error!/n");
}
//处理ftp server 端口
char *ptr1,*ptr2;
char num[1024];
zeromery(num,1024);
//取低位字节
ptr1=recvline+strlen(recvline);
while(*(ptr1)!=‘)‘)
{
ptr1--;
}
ptr2=ptr1;
while(*(ptr2)!=‘,‘)
ptr2--;
strncpy(num,ptr2+1,ptr1-ptr2-1);
i=atoi(num);//将字符串转换成整数
//取高位字节
zeromery(num,1024);
ptr1=ptr2;
ptr2--;
while(*(ptr2)!=‘,‘)
ptr2--;
strncpy(num,ptr2+1,ptr1-ptr2-1);
j=atoi(num);
//初始化服务器数据连接时的端口信息
int data_serviceport;
data_serviceport=j*256+i;
data_sockfd=socket(AF_INET,SOCK_STREAM,0);
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=INADDR_ANY;
serv_addr.sin_port=htons(data_serviceport);
if(connect(data_sockfd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr))==-1)
{
printf("pasv data connect is error!/n");
}
printf("remote-file-pathname=");
scanf("%s",pathname);
printf("local-file-pathname=");
scanf("%s",localpathname);
printf("local:%s remore:%s/n",localpathname,pathname);
fd=fopen(localpathname,"w+");
if(fd==NULL)
{
printf("cannot open file/n");
exit(1);
}
//send the command retr;
zeromery(sendline,1024);
zeromery(recvline,1024);
strcat(sendline,"RETR ");
strcat(sendline,pathname);
strcat(sendline,"/r/n");
printf("%s/n",sendline);
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("retr send is error!/n");
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(recvbytes<0)
{
printf("retr recv is error!/n");
}
if(strncmp(recvline,"400",3)>0)
{
printf("return is error!/n");
}
}
//port mode
/*if(pasv_or_port==1)
{
data_sockfd=socket(AF_INET,SOCK_STREAM,0);
if(data_sockfd<0)
{
printf("创建数据端口连接失败!/n");
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=INADDR_ANY;
serv_addr.sin_port=htons(SERV_PORT);
int ret;
int addrlen;
ret=sizeof(struct sockaddr_in);
getsockname(data_sockfd,(SA*)&serv_addr,&ret);
//处理port 后面要带的参数
char ip[1024];
int i,j;
char data[1024];
zeromery(ip,1024);
zeromery(data,1024);
inet_ntop(AF_INET,&(serv_addr.sin_addr),ip,sizeof(ip));
printf("%s/n",ip);
i=data_sockfd/256;
j=data_sockfd%256;
//将点分十进制的点转换为逗号。
char *ptr1;
ptr1=ip;
while(*(ptr1)!=‘/0‘)
{
if(*(ptr1)==‘.‘)
{
*(ptr1)=‘,‘;
}
ptr1++;
}
strcat(sendline,"PORT ");
strcat(sendline,ip);
strcat(sendline,",");
strcat(sendline,itoa(i,data,10));
strcat(sendline,",");
strcat(sendline,itoa(j,data,10));
strcat(sendline,"/r/n");
printf("--->%s/n",sendline);
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("port send is error!/n");
exit(1);
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(strncmp(recvline,"200",3)==0)
{
printf("%s/n",recv);
}
else
{
printf("port recv is error!/n");
}
}*/
//begin to transpotr data
sleep(1);
int flag=0;
char buffer[65536];
recvdata:
zeromery(buffer,1024);
recvbytes=recv(data_sockfd,buffer,sizeof(buffer),0);
if(recvbytes<0)
{
close(data_sockfd);
goto end;
}
fwrite(buffer,1,recvbytes,fd);
zeromery(recvline,1024);
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(flag==0)
{
if(strncmp(recvline,"226",3)!=0)
{
flag=1;
goto recvdata;
}
}
end:
if(flag!=1)
{
zeromery(recvline,1024);
shutdown(data_sockfd,SHUT_WR);
close(data_sockfd);
}
close(data_sockfd);
/* int err;
char buffer[65535];
err=read(data_sockfd,buffer,sizeof(buffer));
sleep(5);
fwrite(buffer,1,err,fd);
sleep(5);
zeromery(recvline,1024);
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(strncmp(recvline,"226",3)==0)
{
end: printf("226 transfer complete/n");
close(data_sockfd);
}*/
return 0;
}
}
//up 函数
int ftp_up(int control_sockfd)
{
int pasv_or_port;// 定义the ftp协议的两种不同工作mode
int recvbytes,sendbytes;
char sendline[1024],recvline[1024];
struct sockaddr_in serv_addr;
FILE *fd;
int i,j;
int data_sockfd;
//type
zeromery(recvline,1024);
zeromery(sendline,1024);
strcat(sendline,"TYPE ");
strcat(sendline,"I");
strcat(sendline,"/r/n");
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf(" type send is error!/n");
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(strncmp(recvline,"200",3)==0)
{
printf("使用二进制传输数据/n");
}
else
{
printf("type recv is error!/n");
}
if(npsupport==1)
{
//open the file
int size;
char localpathname[60];//预打开的文件路径字符串
int flags;
char pathname[60];
unsigned int mode;
//用户来选择pasv 或者是 port mode
char selectdata_mode_tran[1024];
zeromery(selectdata_mode_tran,1024);
zeromery(sendline,1024);
zeromery(recvline,1024);
pasv_or_port=0;//(默认是pasv模式)
//pasv mode
if(pasv_or_port==0)
{
strcat(sendline,"PASV");
strcat(sendline,"/r/n");
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("pasv send is error!/n");
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(recvbytes<0)
{
printf("pasv recv is error!/n");
}
if(strncmp(recvline,"227",3)==0)
{
char buf[55];
snprintf(buf,51,">>> %s/n",recvline);
printf("%s/n",buf);
}
else
{
printf("pasv recv is error!/n");
}
//处理ftp server 端口
char *ptr1,*ptr2;
char num[1024];
zeromery(num,1024);
//取低位字节
ptr1=recvline+strlen(recvline);
while(*(ptr1)!=‘)‘)
{
ptr1--;
}
ptr2=ptr1;
while(*(ptr2)!=‘,‘)
ptr2--;
strncpy(num,ptr2+1,ptr1-ptr2-1);
i=atoi(num);//将字符串转换成整数
//取高位字节
zeromery(num,1024);
ptr1=ptr2;
ptr2--;
while(*(ptr2)!=‘,‘)
ptr2--;
strncpy(num,ptr2+1,ptr1-ptr2-1);
j=atoi(num);
//初始化服务器数据连接时的端口信息
int data_serviceport;
data_serviceport=j*256+i;
data_sockfd=socket(AF_INET,SOCK_STREAM,0);
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=INADDR_ANY;
serv_addr.sin_port=htons(data_serviceport);
if(connect(data_sockfd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr))==-1)
{
printf("pasv data connect is error!/n");
}
printf("local-file-pathname=");
scanf("%s",pathname);
printf("remote-file-pathname=");
scanf("%s",localpathname);
printf("local:%s remore:%s/n",localpathname,pathname);
fd=fopen(pathname,"r");
if(fd==NULL)
{
printf("cannot open file,请重新输入!/n");
}
//send the command retr;
zeromery(sendline,1024);
zeromery(recvline,1024);
strcat(sendline,"STOR ");
strcat(sendline,localpathname);
strcat(sendline,"/r/n");
printf("%s/n",sendline);
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("stor send is error!/n");
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(recvbytes<0)
{
printf("retr recv is error!/n");
}
if(strncmp(recvline,"150",3)==0)
{
char buf[55];
snprintf(buf,25,">>> %s/n",recvline);
printf("%s/n",buf);
}
}
//port mode
/*if(pasv_or_port==1)
{
data_sockfd=socket(AF_INET,SOCK_STREAM,0);
if(data_sockfd<0)
{
printf("创建数据端口连接失败!/n");
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=INADDR_ANY;
serv_addr.sin_port=htons(SERV_PORT);
int ret;
int addrlen;
ret=sizeof(struct sockaddr_in);
getsockname(data_sockfd,(SA*)&serv_addr,&ret);
//处理port 后面要带的参数
char ip[1024];
int i,j;
char data[1024];
zeromery(ip,1024);
zeromery(data,1024);
inet_ntop(AF_INET,&(serv_addr.sin_addr),ip,sizeof(ip));
printf("%s/n",ip);
i=data_sockfd/256;
j=data_sockfd%256;
//将点分十进制的点转换为逗号。
char *ptr1;
ptr1=ip;
while(*(ptr1)!=‘/0‘)
{
if(*(ptr1)==‘.‘)
{
*(ptr1)=‘,‘;
}
ptr1++;
}
strcat(sendline,"PORT ");
strcat(sendline,ip);
strcat(sendline,",");
strcat(sendline,itoa(i,data,10));
strcat(sendline,",");
strcat(sendline,itoa(j,data,10));
strcat(sendline,"/r/n");
printf("--->%s/n",sendline);
sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
if(sendbytes<0)
{
printf("port send is error!/n");
exit(1);
}
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(strncmp(recvline,"200",3)==0)
{
printf("%s/n",recv);
}
else
{
printf("port recv is error!/n");
}
}*/
//begin to transpotr data
while(!feof(fd))
{
char buffer[65536];
zeromery(buffer,sizeof(buffer));
int size;
size=fread(buffer,1,sizeof(buffer),fd);
if(ferror(fd))
{
printf("read file data is error!/n");
break;
}
else
{
zeromery(sendline,1024);
sendbytes=send(data_sockfd,buffer,size,0);
printf("传输了 %d 个字节/n",sendbytes);
}
close(data_sockfd);
recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
if(strncmp(recvline,"226",3)==0)
{
printf("226 transfer complete");
break;
}
}
return 0;
}
}
linux C 实现FTP客户端
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。