linux下基于tcp的FTP编程

xiaoxiao2021-02-28  117

客户端输入:

ls :           显示本地文件列表

service  ls:       显示服务器文件列表

upload  xxx:      实现xxx文件读取与上传

download  xxx :  实现xxx文件下载与存储

公共函数commonfunc.c 代码:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/stat.h> #include <fcntl.h> #include "commonfunc.h" #include <stddef.h> #include <dirent.h> #define BACKLOG 10//最大连接数 /******************函数作用:网络初始化*****************/ int network_init(int net_type, const char* NET_IP, short NET_NUM) {     int sockfd;     if(-1 == (sockfd = socket(PF_INET, SOCK_STREAM, 0)))   //创建监听套接字     {         perror("Create socket error!");         //exit(EXIT_FAILURE);         return -1;     }     struct sockaddr_in sockadd;     memset(&sockadd, 0, sizeof(sockadd));     sockadd.sin_family = AF_INET;     sockadd.sin_port = htons(NET_NUM);     sockadd.sin_addr.s_addr = inet_addr(NET_IP);     if(NET_CLIENT == net_type)     {            //连接服务器         if(-1 == connect(sockfd, (struct sockaddr*)(&sockadd),\         sizeof(sockadd)))         {             perror("Connect error!");             //exit(EXIT_FAILURE);             return -1;         }     }     else     {         if(NET_SERVER == net_type)         {                 //绑定IP地址端口号             if(-1 == bind(sockfd, (struct sockaddr*)(&sockadd),\             sizeof(sockadd)))             {                 perror("Bind error!");                 return -1;             }                          if(-1 == listen(sockfd, BACKLOG))   //监听客户端             {                 perror("Listen error!");                 return -1;             }         }         else         {             return -1;         }     }     return sockfd; } /**************************命令解析函数************************/ int ftp_cmd_analyse(const char* cmd) {     if(NULL == cmd)     {         return CMD_ERROR;     }     else     {           if(0 == strncmp(cmd, "ls",2))   //列出本地文件列表指令                     return CMD_LS;            else               {             if(0 == strncmp(cmd, "server ls", 9))   //列出服务器文件列表指令                 return CMD_SERVER_LS;               else                {                 if(0 == strcmp(cmd, "quit"))   //断开链接指令                     return CMD_QUIT;                 else                   {                       if(0 == strncmp(cmd, "download ", 9))    //从服务器下载文件指令                       return CMD_DOWNLOAD;                     else                     {                         if(0 == strncmp(cmd, "upload ", 7))    //上传文件到服务器指令                             return CMD_UPLOAD;                         else                         {                             return CMD_ERROR;                         }                     }                 }             }            }     } } /****************从服务器端获取文件列表函数********************/ int ftp_getlist(int getsockfd) {     char GET_BUFF[BUFF_LEN];     int readsize;     sprintf(GET_BUFF,  "server ls");      if(-1 == write(getsockfd, GET_BUFF, BUFF_LEN))   //向服务器发送命令     {         perror("Send cmd error!");         return -1;     }     else     {         while(1)   //循环读取         {             readsize = read(getsockfd, GET_BUFF, BUFF_LEN);             if(readsize <= 0)   //读错误             {                 perror("Get list error!");                 return -1;             }             else             {                 if(0 == strncmp(GET_BUFF, GET_LIST_END, \                 sizeof(GET_LIST_END)))   //判断服务器是否发送完毕                 {                   break;   //发送完毕,退出                 }                 else                 {                     printf("%s\n", GET_BUFF);   //服务器端发送完毕,显示文件                 }             }         }     }     return getsockfd; } /**************把服务器端文件列表发送到客户端函数**************/ int ftp_putlist(int putsockfd) {     const char* LIST_NAME=".";     char PUT_BUFF[BUFF_LEN];     int strn, strm;     DIR* dp;     struct dirent *ep;     struct stat st;     char LIST_PATH[256];     dp = opendir(LIST_NAME);   //打开目录     if(NULL != dp)   //打开目录成功     {         while(ep = readdir(dp))   //循环读目录         {             if(ep->d_name[0] != '.')   //如果不是隐藏文件或目录             {                  sprintf(PUT_BUFF,"%s",ep->d_name);                  write(putsockfd, PUT_BUFF, BUFF_LEN);             }                     }         if(-1 == write(putsockfd, GET_LIST_END, BUFF_LEN))   //发送结束         {             perror("Write endstring error!");             return -1;         }     }     else     {         if(-1 == write(putsockfd, GET_LIST_END, BUFF_LEN))   //发送结束         {             perror("Write endstring error!");             return -1;         }         perror("Can't open the directory!");         return -1;     }     closedir(dp);     return putsockfd; } /*************************文件接收函数*************************/ int ftp_getfile(int getsockfd, const char* GET_FILENAME) {     int getfilefd;   //存放接收文件的文件描述符     int getfilesize;   //实际接收的文件大小     char GET_BUFF[BUFF_LEN];   //接收缓存     //打开一个文件描述符用与保存来自发送端的文件     if(-1  == (getfilefd = open(GET_FILENAME, O_WRONLY|O_CREAT|O_TRUNC, 0666)))     {         perror("Can't open or creat file!");         return -1;     }     else     {         while(getfilesize = read(getsockfd, GET_BUFF, BUFF_LEN) > 0)     //接收文件         {                          if(0 == strncmp(GET_BUFF, "ERROR:", 6))   //接收文件出错             {                 printf("%s", GET_BUFF);                 return -1;             }             else             {                   //取出数据包头中包含的数据区大小                 memcpy(&getfilesize, GET_BUFF, 4);                 /*GET_BUFF+4是因为数据包前四个字节存放的是数据长度,之后的                 1024个字节才存放的实际的数据*/                 if(-1 == write(getfilefd, GET_BUFF+4, getfilesize))                 {                     perror("Download error!");   //接收出错,返回                     close(getfilefd);   //关闭文件                     return -1;                 }                 if(getfilesize < (BUFF_LEN-4))   //已经读取到文件末尾                         break;   //接收结束,退出             }         }         close(getfilefd);   //关闭文件         return getfilefd;   //接收完成,返回接收到的文件的文件描述符。             } } /*****************************文件发送函数********************************/ int ftp_putfile(int putsockfd, const char* PUT_FILENAME) {     int putfilefd;   //存放接收文件的文件描述符     int putfilesize;   //实际接收的文件大小     char PUT_BUFF[BUFF_LEN];         if(-1 == (putfilefd = open(PUT_FILENAME, O_RDONLY)))   //打开文件     {         perror("Open error!");         write(putsockfd, E_NOFILE, BUFF_LEN);   //把错误信息写回。         /*如果不写回错误信息,发送端会卡死*/         return -1;     }     else     {               while((putfilesize = read(putfilefd, PUT_BUFF+4, (BUFF_LEN-4))) \         >0)         {             memcpy(PUT_BUFF, &putfilesize, 4);             if(-1 == write(putsockfd, PUT_BUFF, BUFF_LEN))             {                 perror("Put file error!");                 close(putfilefd);                 return -1;             }             memset(PUT_BUFF, 0, BUFF_LEN);   //清空缓冲区         }     }     close(putfilefd);     return putfilefd; }

//公共函数commonfunc.h头文件

#ifndef __NETWORK_H_ #define __NETWORK_H_ #define NET_SERVER  11 #define NET_CLIENT  22 #define BUFF_LEN 1028//接收发送缓冲区大小 #define CMD_LS         11//列出客户端所有文件 #define CMD_SERVER_LS  22//列出服务器所有文件 #define CMD_DOWNLOAD   33//下载文件 #define CMD_UPLOAD     44//上传文件 #define CMD_QUIT       55//退出 #define CMD_ERROR      -1//错误 #define E_NOFILE    "ERROR:No such file or directory!\n" #define E_DODNLOAD  "ERROR:Download error!\n" #define E_UPLOAD    "ERROR:Upload error!\n" #define GET_LIST_END "SUCCESS:GET LIST SUCCESS!" int     network_init(int net_type, const char* IP_ADDRESS, \ short INET_NUM); void    ftp_print_help(void); int     ftp_cmd_analyse(const char* cmd); int     ftp_getlist(int getsockfd); int     ftp_putlist(int putsockfd); int     ftp_getfile(int getsockfd, const char* GET_FILENAME); int     ftp_putfile(int putsockfd, const char* PUT_FILENAME); #endif

//客户端程序///

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/stat.h> #include <fcntl.h> #include "commonfunc.h" #include <dirent.h> #define INET_NUM 8888   //端口号 #define IP_ADDRESS "10.104.6.110"   //服务器IP #ifndef BUFF_LEN #define BUFF_LEN 1028 #endif #define CMD_LS         11//列出客户端所有文件 #define CMD_SERVER_LS  22//列出服务器所有文件 #define CMD_DOWNLOAD   33//下载文件 #define CMD_UPLOAD     44//上传文件 #define CMD_QUIT       55//退出 #define CMD_ERROR      -1//错误 int main(void) {     int sockfd;     DIR* dp;     struct dirent *ep;     sockfd = network_init(NET_CLIENT, IP_ADDRESS, INET_NUM);   //初始化网络连接     if(sockfd == -1)     {         perror("Network init error!");         exit(EXIT_FAILURE);     }     printf("Connect success!\n\n");     printf("*********Operation Help*********\n");   //操作帮助     printf("显示本地文件列表:        ls\n");     printf("显示服务器文件列表:      server ls\n");     printf("实现xxx文件读取与上传:   upload xxx\n");     printf("实现xxx文件下载与存储:   download xxx\n");     printf("断开socket链接:          quit\n");     printf("*************************************\n\n");     char SEND_BUFF[BUFF_LEN];   //发送数据缓冲区     int cmd_result;   //存放命令解析结果     while(1)     {         fgets(SEND_BUFF, sizeof(SEND_BUFF), stdin);   //输入命令         SEND_BUFF[strlen(SEND_BUFF)-1] = '\0';   //去掉最后输入的回车符                  cmd_result = ftp_cmd_analyse(SEND_BUFF);   //解析输入的指令         switch(cmd_result)         {             case CMD_ERROR:                 printf("ERROR!\n");                 break;                                       case CMD_LS:    //列出本地文件列表                  dp=opendir (".");                  printf("*********File List of Client*********\n");                 while((ep = readdir(dp)))                       {                      if(ep->d_name[0] != '.')                             {                           printf("%s\n",ep->d_name);                             }                       }                 printf("*************************************\n");                   printf("List file success!\n");                      closedir(dp);                break;            ///             case CMD_SERVER_LS:   //列出服务器端可下载的所有文件                 printf("*********File List of Server*********\n");                 if(ftp_getlist(sockfd) == -1)                 {                     printf("List file error!\n");                 }                 else                 {                           printf("*************************************\n");                 printf("List file success!\n");                 }                 break;                                       case CMD_DOWNLOAD:   //从服务器下载文件                 if(write(sockfd, SEND_BUFF, BUFF_LEN) == -1)                 {                     perror("Send cmd error!");                     break;                 }                 if(ftp_getfile(sockfd, SEND_BUFF+9) == -1)   //下载文件                 {                     printf("Download error!\n");                 }                 else                 {                  printf("Download The File Success!!\n");                 }                 break;                         case CMD_UPLOAD:   //上传文件到服务器                                      if(write(sockfd, SEND_BUFF, BUFF_LEN) == -1)                 {                     perror("Send cmd error!");                     break;                 }                 if(ftp_putfile(sockfd, SEND_BUFF+7) == -1)//上传文件                 {                     printf("Upload error!\n");                 }                 else                 {                     printf("Upload The File Success!!\n");                 }                 break;                          case CMD_QUIT:   //断开连接                 printf("Welcome to use again!\nQUIT!\n");                 close(sockfd);//客户端关闭文件描述符后就会自动断开连接                 exit(EXIT_SUCCESS);                 break;                         default:                 break;         }     }     close(sockfd);//客户端关闭文件描述符后就会自动断开连接     return 0; }

//服务器程序///

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/stat.h> #include <fcntl.h> #include "commonfunc.h" #define INET_NUM 8888   //端口号 #define IP_ADDRESS "10.104.6.110"   //IP地址 #define BUFF_LEN 1028 #define CMD_LS          11   //列出客户端所有文件 #define CMD_SERVER_LS   22   //列出服务器所有文件 #define CMD_DOWNLOAD    33   //下载文件 #define CMD_UPLOAD      44   //上传文件 #define CMD_QUIT        55   //退出 #define CMD_ERROR       -1   //错误 int main(void) {     int sockfd;   //网络套接字     sockfd = network_init(NET_SERVER, IP_ADDRESS, INET_NUM);   //初始化网络连接     if(sockfd == -1)     {         perror("Network init error!");         exit(EXIT_FAILURE);     }     printf("LISTEN-ing...\n");     char RCV_BUFF[BUFF_LEN];   //接收缓存     char SEND_BUFF[BUFF_LEN];  //发送缓存     int cmd_result;   //命令解析结果     int connectfd;   //建立连接后用于通信的套接字文件     int readlen;   //读取到的字节数     while(1)     {         if((connectfd = accept(sockfd, NULL, NULL)) == -1)   //链接出错,给出提示         {             perror("Connect error!\n");             break;         }         printf("Connect success!\n");         while(1)         {             readlen = read(connectfd, RCV_BUFF, sizeof(RCV_BUFF));   //接收命令             if(readlen <0)//接收出错             {                 perror("Read error!\n");                 break;             }             else             {                 if(readlen == 0)   //客户端关闭文件描述符后就会断开连接                 {                     printf("Welcome to use again!\nQUIT...\n");                     break;                 }                 else                 {                     printf("**************************\n");                     printf("RECV:%s\n",RCV_BUFF);                     cmd_result = ftp_cmd_analyse(RCV_BUFF);   //解析命令                switch(cmd_result)                     {                         case CMD_ERROR:                             printf("CMD_ERROR!\n");                             break;                         case CMD_SERVER_LS:  //查看服务器文件列表                             if(ftp_putlist(connectfd) == -1)                             {                                 printf("List files error!\n");                             }                             else                             {                                 printf("List files success!\n");                             }                             break;                         case CMD_DOWNLOAD:   //客户端从服务器下载文件                             printf("Put files:%s\n", RCV_BUFF+9);                             if(ftp_putfile(connectfd, RCV_BUFF+9) == -1)                             {                                 printf("Put files error!\n");                             }                             else                             {                                 printf("Put files success!\n");                             }                             break;                         case CMD_UPLOAD:   //客户端上传文件到服务器                             printf("Get files:%s\n", RCV_BUFF+7);                             if(ftp_getfile(connectfd, RCV_BUFF+7) == -1)                             {                                 printf("Get files error!\n");                             }                             else                             {                                 printf("Get files success!\n");                             }                             break;                         default:                             break;                     }                 }             }         }         close(connectfd);//客户端退出,断开连接     }     close(sockfd);     return 0; }

//

转载请注明原文地址: https://www.6miu.com/read-65199.html

最新回复(0)