基于socket的ftp实现

来源:互联网 发布:qq堂有mac 编辑:程序博客网 时间:2024/06/06 00:36
服务器端的实现:
#include <sys/types.h>
#include <sys/socket.h>
#include<netinet/in.h>//sockaddr_in等结构的定义
#include<netdb.h>//addrinfo等结构的定义
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

#define TRUE 1
#define LISTEN_PORT 3499
#define dataLen 1024

char currentDirPath[200];
char currentDirName[30];
char help[]="get 
  get a file from server\n\
put    upload afile to server\n\
pwd   display   the current directory of server\n\
dir    displaythe files in the current directory of server\n\
cd    change thedirectory of server\n\
   display thewhole command which equals 'help'\n\
quit   return\n";

char *getDirName(char *dirPathName);
void cmd_pwd(int sock);
void cmd_dir(int sock);
void cmd_cd(int sock,char *dirName);
void cmd_cdback(int sock);
void cmd_help(int sock);
void cmd_get(int sock,char*fileName);
void cmd_put(int sock,char *fileName);
 
int main(int argc,char *argv[])
{
   int sock,sockmsg, length,lengthmsg;
   char client_cmd[10] ,cmd_arg[20];
   struct sockaddr_inserver;
   struct sockaddr_inservermsg;
   int datasock,msgsock;    
   pid_t child;
 
  // intdatasock;   //data socket
   int rval;
  sock=socket(AF_INET,SOCK_STREAM,0);//创建流式套接字
  sockmsg=socket(AF_INET,SOCK_STREAM,0);
   if(sock<0||sockmsg<0)
   {
    perror("opening stream socket");
    exit(1);
   }
 
  server.sin_family=AF_INET;//AF_INET针对internet,另一种形式AF_UNIX只能够用于单一的Unix系统进程通信(主机通信协议)
  server.sin_addr.s_addr=INADDR_ANY;//表示可以和任何主机通信
  server.sin_port=htons(LISTEN_PORT);//htons将短整形数据转换位网络字节顺序

 
  servermsg.sin_family=AF_INET;
  servermsg.sin_addr.s_addr=INADDR_ANY;
  servermsg.sin_port=htons(LISTEN_PORT+1);

   if (bind(sock,(struct sockaddr*)&server,sizeofserver)<0||bind(sockmsg,(struct sockaddr*)&servermsg,sizeofservermsg)<0)//将本地端口与socket返回的文件描述符绑定在一起
   {
    perror("binding stream socket");
    exit(1);
   }
   
   length=sizeof server;
   lengthmsg=sizeofservermsg;
   if (getsockname(sock,(structsockaddr*)&server,&length)<0||getsockname(sockmsg,(structsockaddr*)&servermsg,&lengthmsg)<0)//用于得套接口的名字
   {
    perror("getting socket name");
    exit(1);
   }
 
   printf("Socket port #%d %d\n",ntohs(server.sin_port),ntohs(servermsg.sin_port));

  memset(currentDirPath,0,sizeof(currentDirPath));//将currentDirpath置零
  getcwd(currentDirPath,sizeof(currentDirPath));//得到当前路径,保存在currentDirPath中
 
   listen(sock,2);//监听,允许最大监听数位2,将绑定的套接字变成监听套接字
   listen(sockmsg,2);
   do  
   {
     datasock = accept(sock,(structsockaddr*)0,(int*)0);//接受请求
     msgsock =accept(sockmsg,(struct sockaddr*)0,(int*)0);
     if (datasock ==-1||msgsock==-1)
      perror("accept");
     else
     {
      if((child=fork())==-1)//创建子进程
      {
         printf("Fork Error!\n");
      }
      //The child process
      if(child==0)
      {
         printf("connection accepted! new clientcomming\n");
loop:
         memset(client_cmd,0,sizeof(client_cmd));
         rval=0;
         rval=read(msgsock,client_cmd,sizeof(client_cmd));//从msgsock中读取数据到client_cmd
 
         if(rval<0)
         {
            perror("reading command failed\n");
         }
         else if(rval==0)
         {
            printf("connection closed.\n");
            close(datasock);//关闭套接字
            close(msgsock);
         }
         else
         {
            if(strcmp(client_cmd,"pwd")==0)
            {
               printf("cmmand pwd\n");
               cmd_pwd(datasock);
               printf("done\n\n");
               goto loop;
            }
            else if(strcmp(client_cmd,"dir")==0)
            {
               printf("command dir\n");
               cmd_dir(datasock);
               printf("done\n\n");
               goto loop;
            }
            else if(strcmp(client_cmd,"cd")==0)
            {
               printf("command cd\n");
               //read the argument
               memset(cmd_arg,0,sizeof(cmd_arg));
               read(msgsock,cmd_arg,sizeof(cmd_arg));
               cmd_cd(datasock,cmd_arg);
               printf("done\n\n");
               goto loop;
            }
            else if(strcmp(client_cmd,"cd..")==0)
            {
               printf("command cd..\n");
               cmd_cdback(datasock);
               printf("done\n\n");
               goto loop;
            }
            else if(strcmp(client_cmd,"get")==0)
            {
               printf("command get\n");
 
               memset(cmd_arg,0,sizeof(cmd_arg));
               read(msgsock,cmd_arg,sizeof(cmd_arg));
               cmd_get(datasock,cmd_arg);
               printf("done\n\n");
               goto loop;
            }
            else if(strcmp(client_cmd,"put")==0)
            {
               printf("command put\n");
 
               memset(cmd_arg,0,sizeof(cmd_arg));
               read(msgsock,cmd_arg,sizeof(cmd_arg));
               cmd_put(datasock,cmd_arg);
               printf("done\n\n");
               goto loop;
            }
            else if(strcmp(client_cmd,"?")==0)
            {
               printf("command ?\n");

               cmd_help(datasock);
               printf("done\n\n");
               goto loop;
            }
            else if(strcmp(client_cmd,"quit")==0)
            {
               printf("quit\n");
               goto endchild;
            }
            else  
            {
               printf("bad request!\n");
               goto loop;
            }
         }
endchild:
         printf("connection closed.\n");
         close(datasock);
         close(msgsock);
         exit(0);
      }
       
     }
   }while(TRUE);
 
   exit(0);
}

//pwd command
void cmd_pwd(int sock)
{
    intlen;
   memset(currentDirPath,0,sizeof(currentDirPath));
   getcwd(currentDirPath,sizeof(currentDirPath));
    char*savePointer=getDirName(currentDirPath);
   strcpy(currentDirName,savePointer);
   len=strlen(currentDirName)+1;
   write(sock,currentDirName,len);
}

//dir command
void cmd_dir(int sock)
{
    DIR *pdir;//目录结构
    charfileName[30];
    charfileInfo[50];
    int i,fcounts=0, len;
    structdirent *pent;//目录的结构体属性
    intfd;
    struct statfileSta;//文件属性
    charfilePath[200];
    
   pdir=opendir(currentDirPath);//打开目录
   pent=readdir(pdir);//读取目录
    
   while(pent!=NULL)
    {
      fcounts++;//计算文件个数
      pent=readdir(pdir);
    }

   write(sock,&fcounts,sizeof(int));//将文件个数写入sock
   closedir(pdir);//关闭目录

   if(fcounts<=0)
    {
      return;
    }
    else
    {
      pdir=opendir(currentDirPath);
      for(i=0;i<fcounts;i++)
      {
         pent=readdir(pdir);
         memset(fileName,0,30);
         memset(fileInfo,0,sizeof(fileInfo));
         strcpy(fileName,pent->d_name);
         
         //check the file is a directory or a file
         memset(filePath,0,sizeof(filePath));
         strcpy(filePath,currentDirPath);
         strcat(filePath,"/");//链接两个字符串
         strcat(filePath,fileName);
         fd=open(filePath,O_RDONLY, S_IREAD);
         
         fstat(fd,&fileSta);//用来读取打开的文件的属性,stat用来读取没有打开的文件的属性
         if(S_ISDIR(fileSta.st_mode))//判断文件是否为目录
         {
            strcat(fileInfo,"dir\t");
            strcat(fileInfo,fileName);
         }
         else
           
            strcat(fileInfo,"file\t");
            strcat(fileInfo,fileName);
         }
         write(sock,fileInfo,sizeof(fileInfo));
      }
      closedir(pdir);
    }
    
    
}

//command cd
void cmd_cd(int sock,char *dirName)
{
    DIR*pdir;
    structdirent *pent;
    charfilename[30];
    inti,fcounts=0;
    intflag=0;

   pdir=opendir(currentDirPath);
   pent=readdir(pdir);
    
   while(pent!=NULL)
    {
      fcounts++;
      pent=readdir(pdir);
    }

   closedir(pdir);

   if(fcounts<=0)
    {
      return;
    }
    else
    {
      pdir=opendir(currentDirPath);
      for(i=0;i<fcounts;i++)
      {
         pent=readdir(pdir);
         if(strcmp(pent->d_name,dirName)==0)
         {
            strcat(currentDirPath,"/");
            strcat(currentDirPath,dirName);
            flag=1;
            break;
         }
      }
      
      if(flag==1)
      {
         write(sock,currentDirPath,sizeof(currentDirPath));
      }
      closedir(pdir);
    }
    
    
}

//command cd..
void cmd_cdback(int sock)
{
    intlen;
    int i,record;

   len=strlen(currentDirPath);
    
   for(i=len-1;i>=0;i--)
    {
      if(currentDirPath[i]=='/')
      {
         currentDirPath[i]='\0';
         break;
      }
      currentDirPath[i]='\0';
    }
}
//command ?
void cmd_help(int sock)
{
    intlen=strlen(help)+1;
   write(sock,help,len);
}

//command get
void cmd_get(int sock,char*fileName)
{
    intfd;
    struct statfileSta;
    longfileSize;
    charfilePath[200], buf[dataLen];
    
   memset(filePath,0,sizeof(filePath));
   strcpy(filePath,currentDirPath);
   strcat(filePath,"/");
   strcat(filePath,fileName);

   fd=open(filePath,O_RDONLY, S_IREAD);
   if(fd!=-1)
    {
      fstat(fd,&fileSta);
      fileSize=(long) fileSta.st_size;//?
      write(sock,&fileSize,sizeof(long));
      memset(buf,0,dataLen);
      while(fileSize>dataLen)
      {
         read(fd,buf,dataLen);
         write(sock,buf,dataLen);
         fileSize=fileSize-dataLen;
      }
      
      read(fd,buf,fileSize);
      write(sock,buf,fileSize);
      close(fd);
      printf("transfer completed\n");
    }
    else
    {
      printf("open file %s failed\n",filePath);
     
}

//command put
void cmd_put(int sock,char *fileName)
   
    intfd;
    longfileSize;
    
    charfilePath[200], buf[dataLen];
   strcpy(filePath,currentDirPath);
   strcat(filePath,"/");
   strcat(filePath,fileName);
    

   fd=open(filePath,O_RDWR|O_CREAT,S_IREAD|S_IWRITE);
   if(fd!=-1)
     
      memset(buf,0,dataLen);
      read(sock,&fileSize,sizeof(long));

      while(fileSize>dataLen)
      {
         read(sock,buf,dataLen);
         write(fd,buf,dataLen);
         fileSize=fileSize-dataLen;
      }
      
      read(sock,buf,fileSize);
      write(fd,buf,fileSize);
      close(fd);
      printf("transfer completed\n");
    }
    else
    {
      printf("open file %s failed\n",filePath);
    }
    
}

//get the last string after the last char '/'
char *getDirName(char *dirPathName)
{
    int i, pos,len;
    char*dirName;

   if(dirPathName==NULL)
    {
      printf("directory absoultly path isnull!\n");
      return NULL;
     
    
   len=strlen(dirPathName);
   for(i=len-1;i>=0;i--)
    {
      if(dirPathName[i]=='/')
      {
         pos=i;
         break;
      }
    }
    
   dirName=(char *)malloc(len-pos+1);
   for(i=pos+1;i<len;i++)
    {
      dirName[i-pos-1]=dirPathName[i];   
    }
    
    returndirName;
}
客户端实现:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>

#define TRUE 1
#define dataLen 1024
char user_cmd[10],cmd_arg[20];
char buf[dataLen];

void cmd_pwd(int sock,int sockmsg);
void cmd_dir(int sock,int sockmsg);
void cmd_cd(int sock,int sockmsg,char *dirName);
void cmd_cdback(int sock,int sockmsg);
void cmd_help(int sock,int sockmsg);
void cmd_get(int sock,int sockmsg,char *fileName);
void cmd_put(int sock,int sockmsg,char *fileName);
void cmd_quit(int sock,int sockmsg);
 
int main(int argc,char *argv[])
{
  int cmd_len,arg_len;
  int sock, sockmsg;
  struct sockaddr_in server, servermsg;
  struct hostent *hp;
  
  sock=socket(AF_INET,SOCK_STREAM,0);
  sockmsg=socket(AF_INET,SOCK_STREAM,0);
    
  if(sock<0||sockmsg<0)
  {
   perror("opening stream socket");
   exit(1);
  }
 
  hp = gethostbyname(argv[1]);
  if (hp==0)
  {
   fprintf(stderr,"%s:unknown host\n",argv[1]);
   exit(2);
  }
 
  server.sin_family=AF_INET;
  server.sin_port=htons(atoi(argv[2]));
  memcpy((char*)&server.sin_addr,(char*)hp->h_addr,hp->h_length);
 
  servermsg.sin_family=AF_INET;
  servermsg.sin_port=htons(atoi(argv[2])+1);
 memcpy((char*)&servermsg.sin_addr,(char*)hp->h_addr,hp->h_length);
 
  if (connect(sock,(struct sockaddr*)&server,sizeofserver)<0||connect(sockmsg,(struct sockaddr*)&servermsg,sizeofservermsg)<0)
  {
    perror("connecting stream socket");
   exit(1);
  }
 
 
  //Get command from command line and do just theaction
  while(TRUE)
  {
   memset(user_cmd,0,10);
   memset(cmd_arg,0,20);

    //First getthe input character by user
   printf("command: ");
   scanf("%s",user_cmd);
   cmd_len=strlen(user_cmd);
    //Then getthe command character and the argument
   if(strcmp(user_cmd,"quit")==0)       //command"quit"
    {
      cmd_quit(sock,sockmsg);
      close(sockmsg);
      close(sock);
      printf("connection closed\n\n");
      exit(0);
      
    elseif(strcmp(user_cmd,"?")==0)     //command"?"
    {
      cmd_help(sock,sockmsg);
    }
    elseif(strcmp(user_cmd,"pwd")==0)    //command"pwd"
    {
      cmd_pwd(sock,sockmsg);
    }
    elseif(strcmp(user_cmd,"dir")==0)     //command"dir"
    {
      cmd_dir(sock,sockmsg);
    }
    elseif(strcmp(user_cmd,"cd")==0)   //commad "cd"
    {
       //inputcommand argument
      scanf("%s",cmd_arg);
      cmd_cd(sock,sockmsg,cmd_arg);
    }
    elseif(strcmp(user_cmd,"cd..")==0)
    {
      cmd_cdback(sock,sockmsg);
    }
    elseif(strcmp(user_cmd,"get")==0)   //command "get"
    {
       //inputcommand argument
      scanf("%s",cmd_arg);
      cmd_get(sock,sockmsg,cmd_arg);
    }
    elseif(strcmp(user_cmd,"put")==0)   //command "put"
     
       //inputcommand argument
      scanf("%s",cmd_arg);
      cmd_put(sock,sockmsg,cmd_arg);
    }
    else
    {
       printf("badcommand!\n");
    }
 
 
}

//command pwd
void cmd_pwd(int sock,int sockmsg)
{
    //intnumRead;
    chardirName[30];
   write(sockmsg,user_cmd,sizeof(user_cmd));
   read(sock,dirName,30);
   printf("%s\n",dirName);
}

//command dir
void cmd_dir(int sock, int sockmsg)
{
    int i,fileNum=0;
    charfileInfo[50];
   
   write(sockmsg,user_cmd,sizeof(user_cmd));
   read(sock,&fileNum,sizeof(int));

   printf("--------------------------------------------------------\n");
    printf("filenumber : %d\n",fileNum);
   if(fileNum>0)
    {
      for(i=0;i<fileNum;i++)
       {
         memset(fileInfo,0,sizeof(fileInfo));
         read(sock,fileInfo,sizeof(fileInfo));
         printf("%s\n",fileInfo);
       }
      printf("--------------------------------------------------------\n");
    }
    elseif(fileNum==0)
    {
      printf("directory of server point is empty.\n");
      return;
    }
    else
    {
      printf("error in command 'dir'\n");
      return;
    }
}

//command cd
void cmd_cd(int sock,int sockmsg,char *dirName)
{
    charcurrentDirPath[200];
   write(sockmsg,user_cmd,sizeof(user_cmd));
   write(sockmsg,cmd_arg,sizeof(cmd_arg));
   read(sock,currentDirPath,sizeof(currentDirPath));
   
    printf("nowin directory : %s\n",currentDirPath);
}

//command cd..
void cmd_cdback(int sock,int sockmsg)
{
   write(sockmsg,user_cmd,sizeof(user_cmd));   
}
//command quit
void cmd_quit(int sock,int sockmsg)
{
   write(sockmsg,user_cmd,sizeof(user_cmd));
}

//command help
void cmd_help(int sock, int sockmsg)
{
    charhelp[300];
   write(sockmsg,user_cmd,sizeof(user_cmd));
   read(sock,help,300);
   
   printf("%s\n",help);   
}

//command get
void cmd_get(int sock,int sockmsg,char *fileName)
{
    intfd;
    longfileSize;
    charlocalFilePath[200];

   write(sockmsg,user_cmd,sizeof(user_cmd));
   write(sockmsg,cmd_arg,sizeof(cmd_arg));
   printf("%s\n%s\n",user_cmd,cmd_arg);
   
   memset(localFilePath,0,sizeof(localFilePath));
   getcwd(localFilePath,sizeof(localFilePath));
   strcat(localFilePath,"/");
   strcat(localFilePath,fileName);

   fd=open(localFilePath,O_RDWR|O_CREAT, S_IREAD|S_IWRITE);
   if(fd!=-1)
     
      memset(buf,0,dataLen);
      read(sock,&fileSize,sizeof(long));
      while(fileSize>dataLen)
       {
         read(sock,buf,dataLen);
         write(fd,buf,dataLen);
         fileSize=fileSize-dataLen;
       }
      
      read(sock,buf,fileSize);
      write(fd,buf,fileSize);
      close(fd);
      printf("download completed\n");
    }
    else
    {
       printf("openfile %s failed\n",localFilePath);
    }
}

//command put
void cmd_put(int sock,int sockmsg,char* fileName)
  
   write(sockmsg,user_cmd,sizeof(user_cmd));
   write(sockmsg,cmd_arg,sizeof(cmd_arg));
   
    intfd;
    longfileSize;
    intnumRead;
    charfilePath[200];
    struct statfileSta;

   memset(filePath,0,sizeof(filePath));
   getcwd(filePath,sizeof(filePath));
   
   strcat(filePath,"/");
   strcat(filePath,fileName);
   
   fd=open(filePath,O_RDONLY, S_IREAD);

   if(fd!=-1)
    {
      fstat(fd,&fileSta);
      fileSize=(long) fileSta.st_size;

      write(sock,&fileSize,sizeof(long));
      memset(buf,0,dataLen);
      while(fileSize>dataLen)
       {
         read(fd,buf,dataLen);
         write(sock,buf,dataLen);
         fileSize=fileSize-dataLen;
       }
      
      read(fd,buf,fileSize);
      write(sock,buf,fileSize);
      close(fd);
      printf("upload completed\n");
    }
    else
    {
       printf("openfile %s failed\n",filePath);
     
}
0 0
原创粉丝点击