蔷薇525 发表于 2015-11-6 08:02:52

ftp协议c语言实现-linux平台

  /*有丰富的注释,很好理解,这是我自己第一次写linux中的网络协议。
* =====================================================================================
*
*       Filename:ftpclient.c
*
*    Description:ftpclient 能上传下载,断点,list 列表等基本的简单东西。下载的时候有时会出现下载不全的问题
  *    如果大家能解决,请给我留言,或者回复,也可发送到下面的邮箱里面。谢谢!让我们一同进步!
*
*      Version:1.0
*      Created:2010年08月04日 08时40分15秒
*       Revision:none
*       Compiler:gcc
*
*         Author:Yang Shao Kun (), cdutyangshaokun@163.com
*      Company:College of Information Engineering of CDUT
*
* =====================================================================================
*/
#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);
intmain(int argc,char **argv)
{
    printf(&quot;ftp>&quot;);
    char command;
    char*cmd;
    scanf(&quot;%s&quot;,command);
    cmd=command;
    while(*(cmd)==' ')
      cmd++;

    if(strncmp(cmd,&quot;login&quot;,5)==0)
    {
      login();
      if(login_yes==1)
      {
            while(1)
            {
            comm:            
                sleep(1);
                printf(&quot;ftp>&quot;);
                zeromery(command,1024);
                scanf(&quot;%s&quot;,command);
                cmd=command;
                while(*(cmd)==' ')
                cmd++;
                if(strncmp(cmd,&quot;pasv&quot;,4)==0)
                {
                  ftp_list(control_sockfd);
                }
                if(strncmp(cmd,&quot;port&quot;,4)==0)
                {
                  ftp_list(control_sockfd);
                }
                if(strncmp(cmd,&quot;list&quot;,4)==0)
                {
                  ftp_pwd(control_sockfd);
                  ftp_list(control_sockfd);
                }
                if(strncmp(cmd,&quot;pwd&quot;,3)==0)
                {
                  ftp_pwd(control_sockfd);
                }
                if(strncmp(cmd,&quot;mkdir&quot;,5)==0)
                {
                  char path;
                  zeromery(path,60);
                  printf(&quot;创建的路径名: &quot;);
                  scanf(&quot;%s&quot;,path);
                  printf(&quot;s/n&quot;,path);
                  ftp_creat_mkd(path,control_sockfd);
                }
                if(strncmp(cmd,&quot;back&quot;,4)==0)
                {
                  ftp_back(control_sockfd);

                  ftp_pwd(control_sockfd);
                }
                if(strncmp(cmd,&quot;cd&quot;,2)==0)
                {
                  int i;
                  char path;
                  zeromery(path,60);
                  printf(&quot;要到的路径:&quot;);
                  scanf(&quot;%s&quot;,path);
                  printf(&quot;%s/n&quot;,path);
                  ftp_changdir(path,control_sockfd);
                }
                if(strncmp(cmd,&quot;get&quot;,3)==0)
                {
                  ftp_pwd(control_sockfd);   
                  ftp_download(control_sockfd);
                }
                if(strncmp(cmd,&quot;up&quot;,3)==0)
                {
                  ftp_pwd(control_sockfd);
                  ftp_up(control_sockfd);      
                }
                if(strncmp(cmd,&quot;quit&quot;,4)==0)
                {
                  printf(&quot;bye^_^/n&quot;);
                  close(control_sockfd);
                  break;
                }
                printf(&quot;支持 list,pwd,mkdir,back,cd,up,get/n&quot;);   
      }
      
    }
    else if(login_yes==0)
    {
      int i;//不成功登录下最多还有两次机会,如果不能在两次登录,则,关闭链接。
      printf(&quot;Can not login vsftpd&quot;);
      for(i=2;i>0;i--)
      {
            printf(&quot;你还有 %d 登录机会/n&quot;,i);            
            login();
            if(login_yes==1)
            {
                goto comm;
            }
      }
      if(i==0)
      {
            printf(&quot;你不能在登录!/n&quot;);
            close(control_sockfd);
      }
            
    }
    else if (strncmp(cmd,&quot;quit&quot;,4)==0)
    {
      ftp_quit(control_sockfd);
      close(control_sockfd);
      
    }
    }
    return 0;
}
int login()
{
    //初始化端口信息
    struct sockaddr_in serv_addr;
    char senddate,recvdate;
    char sendline,recvline;
    struct hostent *host;

    //获取hostent中相关参数
    char name,password;
    printf(&quot;please enter the hostname/n&quot;);
    printf(&quot;ftp-> &quot;);
    scanf(&quot;%s&quot;,name);
    host=gethostbyname(name);
    if(host==NULL)
    {
      printf(&quot;get host by name is error!/n&quot;);
      login_yes=0;
    }
    else
    {
      //创建socket
      control_sockfd=socket(AF_INET,SOCK_STREAM,0);
      if(control_sockfd<0)
      {
            printf(&quot;socket is error/n&quot;);
            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;
      if((connect(control_sockfd,(SA*)&serv_addr,sizeof(serv_addr)))<0)
      {
            printf(&quot;connect is error/n&quot;);
            login_yes=0;
      }
      printf(&quot;connect to %s/n&quot;,inet_ntop(AF_INET,host->h_addr,addr,1024));
      recvdate=recv(control_sockfd,recvline,sizeof(recvline),0);
      if(recvdate==-1)
      {
            printf(&quot;recvdate is connect error/n&quot;);
            login_yes=0;
      }
      else if(strncmp(recvline,&quot;220&quot;,3)==0)
      {
            printf(&quot;connect success,pelase enter username/n&quot;);
            login_yes=1;
      }
      else
      {
            printf(&quot;220 connect is error!&quot;);
            login_yes=0;   
      }

      //ftp用户登录主体部分
      int sendbytes,recvbytes;
      zeromery(name,1024);
      zeromery(password,1024);
      zeromery(recvline,1024);
      zeromery(sendline,1024);
      printf(&quot;ftp-> &quot;);
      scanf(&quot;%s&quot;,name);//可以支持匿名登录vsftpd
      strcat(sendline,&quot;USER &quot;);
      strcat(sendline,name);
      strcat(sendline,&quot;/r/n&quot;);
      printf(&quot;--->%s/n&quot;,sendline);
      sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
      if(sendbytes==-1)
      {
            printf(&quot;send is wrong/n&quot;);
            login_yes=0;
      }
      recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
      if(strncmp(recvline,&quot;331&quot;,3)==0)
      {
            printf(&quot;331 please specify the password./n&quot;);
      }
      else
      {
            printf(&quot;recv date is error./n&quot;);
            login_yes=0;
      }
      zeromery(sendline,1024);
      zeromery(recvline,1024);
      printf(&quot;ftp-> &quot;);
      scanf(&quot;%s&quot;,password);
      strcat(sendline,&quot;PASS &quot;);
      strcat(sendline,password);
      strcat(sendline,&quot;/r/n&quot;);
      printf(&quot;--->%s/n&quot;,sendline);
      sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
      if(sendbytes==-1)
      {
            printf(&quot;pass send is error/n&quot;);
            login_yes=0;
      }
      recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
      if(strncmp(recvline,&quot;230&quot;,3)==0)
      {
            printf(&quot;login success!/n&quot;);
            login_yes=1;
      }
      else
      {
            printf(&quot;pass recv is error/n&quot;);
            login_yes=0;
      }


      //支持断点续传
      zeromery(sendline,1024);
      zeromery(recvline,1024);
      strcat(sendline,&quot;REST &quot;);
      strcat(sendline,&quot;0&quot;);
      strcat(sendline,&quot;/r/n&quot;);
      printf(&quot;--->%s/n&quot;,sendline);
      sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
      if(sendbytes==-1)
      {
            printf(&quot;rest send is error!/n&quot;);
            login_yes=0;
      }
      recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
      if(recvbytes==-1)
      {
            printf(&quot;rest recv date is error./n&quot;);   
            login_yes=0;   
      }
      if(strncmp(recvline,&quot;350 Restart position accepted (0).&quot;,34)==0)
      {
            npsupport=1;
            printf(&quot;support 断点续传/n&quot;);
            login_yes=1;
      }
      else
      {
            npsupport=0;
            printf(&quot;not support 断点续传/n&quot;);
            login_yes=0;   
      }
   

      //获取服务器版本信息
      zeromery(recvline,1024);
      zeromery(sendline,1024);
      strcat(sendline,&quot;SYST&quot;);
      strcat(sendline,&quot;/r/n&quot;);
      printf(&quot;--->%s/n&quot;,sendline);
      sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
      if(sendbytes==-1)
      {
            printf(&quot;syst send is error/n&quot;);
            login_yes=0;
      }
      recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
      if(recvbytes==-1)
      {
            printf(&quot;syst recv is error/n&quot;);
            login_yes=0;
      }
      if(strncmp(recvline,&quot;215 UNIX Type: L8&quot;,17)==0)
      {
            printf(&quot;%s&quot;,recvline);
            login_yes=1;
      }
      else
      {
            printf(&quot;syst recv connectin is error/n&quot;);
            login_yes=0;
      }   
    }
   
    return login_yes;
}

//数组初始化
void zeromery(char *a,int len)
{
    int i;
    len=sizeof(a);
    for(i=0;i<len;i++)
    {
      a=0;
    }
}

//quit函数,control_sockfd,通过实参传递
void ftp_quit(int control_sockfd )
{
    char sendline;
    char recvline;
    int recvbytes;
    int sendbytes;
    zeromery(sendline,1024);
    zeromery(recvline,1024);
    strcat(sendline,&quot;QUIT&quot;);
    strcat(sendline,&quot;/r/n&quot;);
    sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
    if(sendbytes<0)
    {
      printf(&quot;quit send is error!/n&quot;);
      exit(1);
    }
    recvbytes=recv(control_sockfd,recvline,strlen(recvline),0);
    if(strncmp(recvline,&quot;221&quot;,3)==0)
    {
      printf(&quot;221 bye!^_^&quot;);
      exit(1);
    }
    else
    {
      printf(&quot;quit recv is error!/n&quot;);
      exit(1);
    }
}


//mkd,在所在路径中创建目录 函数
void ftp_creat_mkd(char *path,int control_sockfd)
{
    char sendline;
    char recvline;
    zeromery(sendline,1024);
    zeromery(recvline,1024);
    int recvbytes,sendbytes;
    int issuccess;
    strcat(sendline,&quot;MKD &quot;);
    strcat(sendline,path);
    strcat(sendline,&quot;/r/n&quot;);
    printf(&quot;%s/n&quot;,sendline);
    sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
    if(sendbytes<0)
    {
      printf(&quot;mkd send is error!&quot;);
      exit(1);
    }
    recvbytes=recv(control_sockfd,recvline,strlen(recvline),0);
    if(strncmp(recvline,&quot;257&quot;,3)==0)
    {
      issuccess=1;
    }
    else
    {
      issuccess=0;
    }
}


//改变目录函数chdir
voidftp_changdir(char *dir,int control_sockfd)
{
   
    char sendline;
    char recvline;
    int recvbytes,sendbytes;
    zeromery(sendline,1024);
    zeromery(recvline,1024);
    strcat(sendline,&quot;CWD &quot;);
    strcat(sendline,dir);
    strcat(sendline,&quot;/r/n&quot;);
    printf(&quot;%s/n&quot;,sendline);
    sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
    if(sendbytes<0)
    {
      printf(&quot;cwd send is error!/n&quot;);
    }
    recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
    if(recvbytes<0)
    {
      printf(&quot;cwd recv is error!/n&quot;);
    }
    if(strncmp(recvline,&quot;250&quot;,3)==0)
    {
                char buf;
                snprintf(buf,39,&quot;>>> %s/n&quot;,recvline);
                printf(&quot;%s/n&quot;,buf);
    }
    else
    {
      printf(&quot;cwd chdir is error!/n&quot;);
      exit(1);
    }
}


//pwd 命令函数
//在应答中返回当前工作目录,“pwd”+/r/n
void ftp_pwd(int control_sockfd)
{
    int recvbytes,sendbytes;
    char sendline,recvline;
    zeromery(sendline,1024);
    zeromery(recvline,1024);
    strcat(sendline,&quot;PWD&quot;);
    strcat(sendline,&quot;/r/n&quot;);
    sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
    if(sendbytes<0)
    {
      printf(&quot;pwd,send is error/n&quot;);
    }
    recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
    if(strncmp(recvline,&quot;257&quot;,3)==0)
    {
      int i=0;
      char *ptr;
      char currendir;
      zeromery(currendir,1024);
      ptr=recvline+5;
      while(*(ptr)!='&quot;')
      {
            currendir=*(ptr);
            ptr++;
      }
      currendir='/0';
      printf(&quot;current directory is:%s/n&quot;,currendir);

    }
    else
    {
      printf(&quot;pwd,recv is error!/n&quot;);
    }
}



//获取服务器文件列表
//list命令,是数据通道,通过的是21端口。the function 's struct is &quot;the data //transport mode&quot;(ascii or b) puls &quot;the data mode to transport&quot;(pasv or port//) puls &quot;the list command&quot;
void ftp_list(int control_sockfd)
{
    int pasv_or_port;// 定义the ftp协议的两种不同工作mode
    int recvbytes,sendbytes;
    char sendline,recvline;
    struct sockaddr_in serv_addr;
    int i,j;
    int flag=0;
    int data_sockfd;

    //用户来选择pasv 或者是 port mode(默认的是pasv模式)
    char selectdata_mode_tran;
    zeromery(selectdata_mode_tran,1024);
    zeromery(sendline,1024);
    zeromery(recvline,1024);
    //printf(&quot;ftp->ftp协议工作方式选择(pasv or port)/n&quot;);
    //printf(&quot;ftp->&quot;);
//    scanf(&quot;%s&quot;,selectdata_mode_tran);
    //if(strncmp(selectdata_mode_tran,&quot;pasv&quot;,4)==0)
    //{
      pasv_or_port=0;
//    }
//    if(strncmp(selectdata_mode_tran,&quot;port&quot;,4)==0)
//    {
//      pasv_or_port=1;
//    }
    //pasv mode
    if(pasv_or_port==0)
    {
      strcat(sendline,&quot;PASV&quot;);
      strcat(sendline,&quot;/r/n&quot;);
      sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
      if(sendbytes<0)
      {
            printf(&quot;pasv send is error!/n&quot;);
      }
      recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
      if(recvbytes<0)
      {
            printf(&quot;pasv recv is error!/n&quot;);
      }
      if(strncmp(recvline,&quot;227&quot;,3)==0)
      {
            printf(&quot;%s/n&quot;,recvline);
      }
      else
      {
            printf(&quot;pasv recv is error!/n&quot;);
      }   
      //处理ftp server 端口
      char *ptr1,*ptr2;
      char num;
      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(&quot;pasv data connect is error!/n&quot;);
      }
    }
    //port mode
    if(pasv_or_port==1)
    {
      data_sockfd=socket(AF_INET,SOCK_STREAM,0);
      if(data_sockfd<0)
      {
            printf(&quot;创建数据端口连接失败!/n&quot;);
      }
      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;
      int i,j;
      char data;
      zeromery(ip,1024);
      zeromery(data,1024);
      inet_ntop(AF_INET,&(serv_addr.sin_addr),ip,sizeof(ip));
      printf(&quot;%s/n&quot;,ip);
      i=data_sockfd/256;
      j=data_sockfd%256;

      //将点分十进制的点转换为逗号。
      char *ptr1;
      ptr1=ip;
      while(*(ptr1)!='/0')
      {
            if(*(ptr1)=='.')
            {
                *(ptr1)=',';
            }
            ptr1++;
      }

      strcat(sendline,&quot;PORT &quot;);
      strcat(sendline,ip);
      strcat(sendline,&quot;,&quot;);
      strcat(sendline,itoa(i,data,10));
      strcat(sendline,&quot;,&quot;);
      strcat(sendline,itoa(j,data,10));
      strcat(sendline,&quot;/r/n&quot;);
      printf(&quot;--->%s/n&quot;,sendline);
      sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
      if(sendbytes<0)
      {
            printf(&quot;port send is error!/n&quot;);
            exit(1);
      }
      recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
      if(strncmp(recvline,&quot;200&quot;,3)==0)
      {
            printf(&quot;%s/n&quot;,recvline);
      }
      else
      {
            printf(&quot;port recv is error!/n&quot;);
      }

    }

    //type
    zeromery(recvline,1024);
    zeromery(sendline,1024);
    strcat(sendline,&quot;TYPE &quot;);
    strcat(sendline,&quot;I&quot;);
    strcat(sendline,&quot;/r/n&quot;);
    sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
    if(sendbytes<0)
    {
      printf(&quot; type send is error!/n&quot;);
    }
    recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
    if(strncmp(recvline,&quot;200&quot;,3)==0)
    {
      printf(&quot;使用二进制传输数据/n&quot;);
    }
    else
    {
      printf(&quot;type recv is error!/n&quot;);
    }
      

    //list
    zeromery(sendline,1024);
    zeromery(recvline,1024);
    strcat(sendline,&quot;LIST&quot;);
    strcat(sendline,&quot;/r/n&quot;);
    sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
    if(sendbytes<0)
    {
      printf(&quot;list send is error!/n&quot;);
    }
recvdata:
    sleep(1);
    recvbytes=recv(data_sockfd,recvline,sizeof(recvline),0);
    if(recvbytes<0)
    {
      close(data_sockfd);
      goto ending;
    }
    printf(&quot;%s&quot;,recvline);
    if(flag==0)
    {
      zeromery(recvline,1024);
      recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
      if(strncmp(recvline,&quot;226&quot;,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;
    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,recvline;
    int recvbytes,sendbytes;
    zeromery(sendline,1024);
    zeromery(recvline,1024);
    strcat(sendline,&quot;CDUP&quot;);
    strcat(sendline,&quot;/r/n&quot;);
    sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
    if(sendbytes<0)
    {
      printf(&quot;cdup send is error !/n&quot;);
    }
    recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
    if(recvbytes<0)
    {
      printf(&quot;cdup recv is error !/n&quot;);
    }
    if(strncmp(recvline,&quot;250&quot;,3)==0)
    {
      printf(&quot;请求的文件操作已经成功/n&quot;);
    }
}
//stru命令的实现
void ftp_stru(int control_sockfd)
{
    int recvbytes,sendbytes;
    char sendline,recvline;
    zeromery(sendline,1024);
    zeromery(recvline,1024);
    strcat(sendline,&quot;STRU&quot;);
    strcat(sendline,&quot;F&quot;);
    strcat(sendline,&quot;/r/n&quot;);
    sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
    if(sendbytes<0)
    {
      printf(&quot;stru send is error!/n&quot;);
    }
    recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
    if(recvbytes<0)
    {
      printf(&quot;stru recv is error!/n&quot;);
    }
    if(strncmp(recvline,&quot;200&quot;,3)==0)
    {
      f=0;
    }

}

//断点函数的支持
void ftp_rest(int control_sockfd)
{

    int recvbytes,sendbytes;
    char sendline,recvline;
    zeromery(sendline,1024);
    zeromery(recvline,1024);
    strcat(sendline,&quot;REST &quot;);
    strcat(sendline,&quot;500&quot;);
    strcat(sendline,&quot;/r/n&quot;);
    sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
    if(sendbytes<0)
    {
      printf(&quot;stru send is error!/n&quot;);
    }
    recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
    if(recvbytes<0)
    {
      printf(&quot;stru recv is error!/n&quot;);
    }
    if(strncmp(recvline,&quot;350&quot;,3)==0)
    {
      printf(&quot;%s/n&quot;,recvline);
    }
}

//下载的实现函数
int ftp_download(int control_sockfd)
{
   
    int pasv_or_port;// 定义the ftp协议的两种不同工作mode
    int recvbytes,sendbytes;
    char sendline,recvline;
    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,&quot;TYPE &quot;);
    strcat(sendline,&quot;I&quot;);
    strcat(sendline,&quot;/r/n&quot;);
    sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
    if(sendbytes<0)
    {
            printf(&quot; type send is error!/n&quot;);
    }
    recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
    if(strncmp(recvline,&quot;200&quot;,3)==0)
    {
      printf(&quot;使用二进制传输数据/n&quot;);
    }
    else
    {
      printf(&quot;type recv is error!/n&quot;);
    }

    if(npsupport==1)
    {
      //open the file
      int size;
      char localpathname;//预打开的文件路径字符串
      int flags;
      char pathname;
      unsigned int mode;
      //用户来选择pasv 或者是 port mode
      char selectdata_mode_tran;
      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,&quot;PASV&quot;);
            strcat(sendline,&quot;/r/n&quot;);
            sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
            if(sendbytes<0)
            {
                printf(&quot;pasv send is error!/n&quot;);
            }
            zeromery(recvline,1024);
            recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
            if(recvbytes<0)
            {
                printf(&quot;pasv recv is error!/n&quot;);
            }
            if(strncmp(recvline,&quot;227&quot;,3)==0)
            {
                char buf;
                snprintf(buf,51,&quot;>>> %s/n&quot;,recvline);
                printf(&quot;%s/n&quot;,buf);
            }
            else
            {
                printf(&quot;pasv recv is error!/n&quot;);
            }   
            //处理ftp server 端口
            char *ptr1,*ptr2;
            char num;
            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(&quot;pasv data connect is error!/n&quot;);
            }
            printf(&quot;remote-file-pathname=&quot;);
            scanf(&quot;%s&quot;,pathname);
            printf(&quot;local-file-pathname=&quot;);
            scanf(&quot;%s&quot;,localpathname);
            printf(&quot;local:%s remore:%s/n&quot;,localpathname,pathname);
            fd=fopen(localpathname,&quot;w+&quot;);
            if(fd==NULL)
            {
                printf(&quot;cannot open file/n&quot;);
                exit(1);
            }

   
            //send the command retr;
            zeromery(sendline,1024);
            zeromery(recvline,1024);
            strcat(sendline,&quot;RETR &quot;);
            strcat(sendline,pathname);
            strcat(sendline,&quot;/r/n&quot;);
            printf(&quot;%s/n&quot;,sendline);
            sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
            if(sendbytes<0)
            {
                printf(&quot;retr send is error!/n&quot;);
            }
            recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
            if(recvbytes<0)
            {
                printf(&quot;retr recv is error!/n&quot;);
            }
            if(strncmp(recvline,&quot;400&quot;,3)>0)
            {
                printf(&quot;return is error!/n&quot;);
            }
      }
      //port mode
      /*if(pasv_or_port==1)
      {
            data_sockfd=socket(AF_INET,SOCK_STREAM,0);
            if(data_sockfd<0)
            {
                printf(&quot;创建数据端口连接失败!/n&quot;);
            }
            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;
            int i,j;
            char data;
            zeromery(ip,1024);
            zeromery(data,1024);
            inet_ntop(AF_INET,&(serv_addr.sin_addr),ip,sizeof(ip));
            printf(&quot;%s/n&quot;,ip);
            i=data_sockfd/256;
            j=data_sockfd%256;

            //将点分十进制的点转换为逗号。
            char *ptr1;
            ptr1=ip;
            while(*(ptr1)!='/0')
            {
                if(*(ptr1)=='.')
                {
                  *(ptr1)=',';
                }
                ptr1++;
            }

            strcat(sendline,&quot;PORT &quot;);
            strcat(sendline,ip);
            strcat(sendline,&quot;,&quot;);
            strcat(sendline,itoa(i,data,10));
            strcat(sendline,&quot;,&quot;);
            strcat(sendline,itoa(j,data,10));
            strcat(sendline,&quot;/r/n&quot;);
            printf(&quot;--->%s/n&quot;,sendline);
            sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
            if(sendbytes<0)
            {
                printf(&quot;port send is error!/n&quot;);
                exit(1);
            }
            recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
            if(strncmp(recvline,&quot;200&quot;,3)==0)
            {
                printf(&quot;%s/n&quot;,recv);
            }
            else
            {
                printf(&quot;port recv is error!/n&quot;);
            }

      }*/
      //begin to transpotr data
      sleep(1);
      int flag=0;
      char buffer;
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,&quot;226&quot;,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;
    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,&quot;226&quot;,3)==0)
    {
    end:    printf(&quot;226 transfer complete/n&quot;);
      close(data_sockfd);
    }*/
    return 0;
    }
}


//up 函数
int ftp_up(int control_sockfd)
{
      
    int pasv_or_port;// 定义the ftp协议的两种不同工作mode
    int recvbytes,sendbytes;
    char sendline,recvline;
    struct sockaddr_in serv_addr;
    FILE *fd;
    int i,j;
    int data_sockfd;
    //type
    zeromery(recvline,1024);
    zeromery(sendline,1024);
    strcat(sendline,&quot;TYPE &quot;);
    strcat(sendline,&quot;I&quot;);
    strcat(sendline,&quot;/r/n&quot;);
    sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
    if(sendbytes<0)
    {
            printf(&quot; type send is error!/n&quot;);
    }
    recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
    if(strncmp(recvline,&quot;200&quot;,3)==0)
    {
      printf(&quot;使用二进制传输数据/n&quot;);
    }
    else
    {
      printf(&quot;type recv is error!/n&quot;);
    }

    if(npsupport==1)
    {
      //open the file
      int size;
      char localpathname;//预打开的文件路径字符串
      int flags;
      char pathname;
      unsigned int mode;
      //用户来选择pasv 或者是 port mode
      char selectdata_mode_tran;
      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,&quot;PASV&quot;);
            strcat(sendline,&quot;/r/n&quot;);
            sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
            if(sendbytes<0)
            {
                printf(&quot;pasv send is error!/n&quot;);
            }
            recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
            if(recvbytes<0)
            {
                printf(&quot;pasv recv is error!/n&quot;);
            }
            if(strncmp(recvline,&quot;227&quot;,3)==0)
            {
                char buf;
                snprintf(buf,51,&quot;>>> %s/n&quot;,recvline);
                printf(&quot;%s/n&quot;,buf);
            }
            else
            {
                printf(&quot;pasv recv is error!/n&quot;);
            }   
            //处理ftp server 端口
            char *ptr1,*ptr2;
            char num;
            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(&quot;pasv data connect is error!/n&quot;);
            }
                printf(&quot;local-file-pathname=&quot;);
                scanf(&quot;%s&quot;,pathname);
                printf(&quot;remote-file-pathname=&quot;);
                scanf(&quot;%s&quot;,localpathname);
                printf(&quot;local:%s remore:%s/n&quot;,localpathname,pathname);
                fd=fopen(pathname,&quot;r&quot;);
                if(fd==NULL)
                {
                  printf(&quot;cannot open file,请重新输入!/n&quot;);
                }

            //send the command retr;
            zeromery(sendline,1024);
            zeromery(recvline,1024);
            strcat(sendline,&quot;STOR &quot;);
            strcat(sendline,localpathname);
            strcat(sendline,&quot;/r/n&quot;);
            printf(&quot;%s/n&quot;,sendline);
            sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
            if(sendbytes<0)
            {
                printf(&quot;stor send is error!/n&quot;);
            }
            recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
            if(recvbytes<0)
            {
                printf(&quot;retr recv is error!/n&quot;);
            }
            if(strncmp(recvline,&quot;150&quot;,3)==0)
            {
                char buf;
                snprintf(buf,25,&quot;>>> %s/n&quot;,recvline);
                printf(&quot;%s/n&quot;,buf);
            }
      }
      //port mode
      /*if(pasv_or_port==1)
      {
            data_sockfd=socket(AF_INET,SOCK_STREAM,0);
            if(data_sockfd<0)
            {
                printf(&quot;创建数据端口连接失败!/n&quot;);
            }
            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;
            int i,j;
            char data;
            zeromery(ip,1024);
            zeromery(data,1024);
            inet_ntop(AF_INET,&(serv_addr.sin_addr),ip,sizeof(ip));
            printf(&quot;%s/n&quot;,ip);
            i=data_sockfd/256;
            j=data_sockfd%256;

            //将点分十进制的点转换为逗号。
            char *ptr1;
            ptr1=ip;
            while(*(ptr1)!='/0')
            {
                if(*(ptr1)=='.')
                {
                  *(ptr1)=',';
                }
                ptr1++;
            }

            strcat(sendline,&quot;PORT &quot;);
            strcat(sendline,ip);
            strcat(sendline,&quot;,&quot;);
            strcat(sendline,itoa(i,data,10));
            strcat(sendline,&quot;,&quot;);
            strcat(sendline,itoa(j,data,10));
            strcat(sendline,&quot;/r/n&quot;);
            printf(&quot;--->%s/n&quot;,sendline);
            sendbytes=send(control_sockfd,sendline,strlen(sendline),0);
            if(sendbytes<0)
            {
                printf(&quot;port send is error!/n&quot;);
                exit(1);
            }
            recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
            if(strncmp(recvline,&quot;200&quot;,3)==0)
            {
                printf(&quot;%s/n&quot;,recv);
            }
            else
            {
                printf(&quot;port recv is error!/n&quot;);
            }

      }*/
      //begin to transpotr data
    while(!feof(fd))
    {      
      char buffer;
      zeromery(buffer,sizeof(buffer));
      int size;
      size=fread(buffer,1,sizeof(buffer),fd);
      if(ferror(fd))
      {
            printf(&quot;read file data is error!/n&quot;);
            break;
      }
      else
      {
            zeromery(sendline,1024);
            sendbytes=send(data_sockfd,buffer,size,0);
            printf(&quot;传输了 %d 个字节/n&quot;,sendbytes);
      }
      close(data_sockfd);
      recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0);
      if(strncmp(recvline,&quot;226&quot;,3)==0)
      {
            printf(&quot;226 transfer complete&quot;);
            break;
      }
    }
    return 0;
    }
}
             版权声明:本文为博主原创文章,未经博主允许不得转载。
页: [1]
查看完整版本: ftp协议c语言实现-linux平台