TCP ftp服务器模型 《超经典》

来源:互联网 发布:c语言编译器好用的 编辑:程序博客网 时间:2024/05/20 08:43
//header.h#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <sys/types.h>       #include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#include <dirent.h>#define BUFFERSIZE 1024typedef struct sockaddr SA;


//服务器端#include "header.h"void ProcessList(int connfd);void ProcessGet(int connfd, char buf[]);void ProcessPut(int connfd, char buf[]);void ProcessList(int connfd){char buf[BUFFERSIZE];DIR *mydir;struct dirent *myitem;mydir = opendir(".");while ((myitem = readdir(mydir)) != NULL){if ((strcmp(myitem->d_name, ".") == 0)        || (strcmp(myitem->d_name, "..") == 0))  continue;strcpy(buf, myitem->d_name);send(connfd, buf, BUFFERSIZE, 0);}closedir(mydir);return;}void ProcessGet(int connfd, char buf[]){int fd, nbyte;if ((fd = open(buf+1, O_RDONLY)) < 0){fprintf(stderr, "fail to open %s : %s\n", buf+1, strerror(errno));buf[0] = 'N';send(connfd, buf, BUFFERSIZE, 0);return;}buf[0] = 'Y';send(connfd, buf, BUFFERSIZE, 0);while ((nbyte = read(fd, buf, BUFFERSIZE)) > 0){send(connfd, buf, nbyte, 0);}close(fd);return;}void ProcessPut(int connfd, char buf[]){int fd, nbyte;if ((fd = open(buf+1, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0){printf("fail to create %s on server\n", buf+1);return;}while ((nbyte = recv(connfd, buf, BUFFERSIZE, 0)) > 0){write(fd, buf, nbyte);}close(fd);return;}int main(int argc, char *argv[]){int listenfd, connfd;char buf[BUFFERSIZE];struct sockaddr_in server_addr;if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0){fprintf(stderr, "fail to socket : %s\n", strerror(errno));exit(-1);}#ifdef _DEBUG_printf("socket is %d\n", listenfd);#endifmemset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = PF_INET;server_addr.sin_port = htons(8888);server_addr.sin_addr.s_addr = htonl(INADDR_ANY);if (bind(listenfd, (SA *)&server_addr, sizeof(server_addr)) < 0){perror("fail to bind");exit(-1);}listen(listenfd, 5);while ( 1 ){if ((connfd = accept(listenfd, NULL, NULL)) < 0)//等待客户端连接{perror("fail to accept");break;}recv(connfd, buf, BUFFERSIZE, 0);    //第一步收到客户端的业务请求switch (buf[0]){case 'L' :ProcessList(connfd);break;case 'G' :ProcessGet(connfd, buf);break;case 'P' :ProcessPut(connfd, buf);break;}close(connfd);}   return 0;}

//客户端#include "header.h"void PrintHelp();void ProcessList(struct sockaddr_in server_addr);void ProcessGet(struct sockaddr_in server_addr, char command[]);void ProcessPut(struct sockaddr_in server_addr, char command[]);void PrintHelp(){printf("help : display help info\n");printf("list : get file list of server\n");printf("get  : get <file>\n");printf("put  : put <file>\n");printf("quit : quit the client\n");return;}void ProcessList(struct sockaddr_in server_addr){ int sockfd, nbyte;char buf[BUFFERSIZE]; //设置成局部变量可以互不影响if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0){ printf("fail to list\n");return;}if (connect(sockfd, (SA *)&server_addr, sizeof(server_addr)) < 0){printf("fail to connect server\n");goto ERROR_1;}strcpy(buf, "L");       //第一步要告诉服务器客户端需要干嘛send(sockfd, buf, BUFFERSIZE, 0);while ((nbyte = recv(sockfd, buf, BUFFERSIZE, 0)) != 0) //0放送方式 通常为0{printf("%s\n", buf);}ERROR_1:close(sockfd);return;}void ProcessGet(struct sockaddr_in server_addr, char command[]){int sockfd, nbyte, fd;char buf[BUFFERSIZE];if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0){printf("fail to get\n");return;}if (connect(sockfd, (SA *)&server_addr, sizeof(server_addr)) < 0){printf("fail to connect server\n");goto ERROR_2;}sprintf(buf, "G%s", command+4);send(sockfd, buf, BUFFERSIZE, 0);recv(sockfd, buf, BUFFERSIZE, 0);if (buf[0] == 'N') // no such file{printf("No such file on server\n");goto ERROR_2;}if ((fd = open(command+4, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0){printf("fail to create local file %s\n", command+4);goto ERROR_2;}while ((nbyte = recv(sockfd, buf, BUFFERSIZE, 0)) > 0){write(fd, buf, nbyte);}close(fd);ERROR_2:close(sockfd);return;}void ProcessPut(struct sockaddr_in server_addr, char command[]){int sockfd, fd, nbyte;char buf[BUFFERSIZE];if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0){printf("fail to get\n");return;}if (connect(sockfd, (SA *)&server_addr, sizeof(server_addr)) < 0){printf("fail to connect server\n");goto ERROR_3;}if ((fd = open(command+4, O_RDONLY)) < 0){printf("fail to open %s\n", command+4);goto ERROR_3;}sprintf(buf, "P%s", command+4);send(sockfd, buf, BUFFERSIZE, 0);while ((nbyte = read(fd, buf, BUFFERSIZE)) > 0){send(sockfd, buf, nbyte, 0);}close(fd);ERROR_3:close(sockfd);return;}int main(int argc, char *argv[]){int sockfd, fd, nbyte;char command[32];struct sockaddr_in server_addr;if (argc < 3){printf("Usage : %s <server_ip> : <port>\n", argv[0]);exit(-1);}// XXX:step 1  int socket(int domain, int type, int protocol);if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0){fprintf(stderr, "fail to socket : %s\n", strerror(errno));exit(-1);}#ifdef _DEBUG_printf("socket is %d\n", sockfd);#endif// XXX:step 2  int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = PF_INET;server_addr.sin_port = htons(atoi(argv[2]));server_addr.sin_addr.s_addr = inet_addr(argv[1]);//server_addr.sin_addr.s_addr = htonl(INADDR_ANY);while ( 1 ){printf("<client> ");fgets(command, 32, stdin);command[strlen(command)-1] = '\0';      // overwrite the '\n'需要减一if (strcmp(command, "help") == 0){   PrintHelp();}else if (strcmp(command, "list") == 0){ProcessList(server_addr);}else if (strncmp(command, "get ", 4) == 0){ProcessGet(server_addr, command);}else if (strncmp(command, "put ", 4) == 0){ProcessPut(server_addr, command);}else if (strcmp(command, "quit") == 0){printf("Bye\n");break;}else{printf("wrong command, 'help' for command list\n");}}   return 0;}