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;
    }
}





你可能感兴趣的:(ftp)