Linux C 编写的简易FTP程序
服务端代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
//server.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <dirent.h> #include <fcntl.h> #define N 256 typedef struct sockaddr SA; void commd_ls(int); void commd_get(int, char *); void commd_put(int, char *); int main(int arg, char *argv[]) { int ser_sockfd, cli_sockfd; struct sockaddr_in ser_addr, cli_addr; socklen_t ser_len, cli_len; char commd[N]; bzero(commd, N); if ((ser_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("Sokcet Error!\n"); return -1; } bzero(&ser_addr, sizeof(ser_addr)); ser_addr.sin_family = AF_INET; ser_addr.sin_addr.s_addr = htonl(INADDR_ANY); ser_addr.sin_port = htons(8989); ser_len = sizeof(ser_addr); if ((bind(ser_sockfd, (SA *) & ser_addr, ser_len)) < 0) { printf("Bind Error!\n"); return -1; } if (listen(ser_sockfd, 5) < 0) { printf("Linsten Error!\n"); return -1; } bzero(&cli_addr, sizeof(cli_addr)); ser_len = sizeof(cli_addr); while (1) { printf("server_ftp>"); if ((cli_sockfd = accept(ser_sockfd, (SA *) & cli_addr, &cli_len)) < 0) { printf("Accept Error!\n"); exit(1); } if (read(cli_sockfd, commd, N) < 0) { printf("Read Error!\n"); exit(1); } printf("recvd [ %s ]\n", commd); if (strncmp(commd, "ls", 2) == 0) { commd_ls(cli_sockfd); } else if (strncmp(commd, "get", 3) == 0) { commd_get(cli_sockfd, commd + 4); } else if (strncmp(commd, "put", 3) == 0) { commd_put(cli_sockfd, commd + 4); } else { printf("Error!Command Error!\n"); } } return 0; } void commd_ls(int sockfd) { DIR *mydir = NULL; struct dirent *myitem = NULL; char commd[N]; bzero(commd, N); if ((mydir = opendir(".")) == NULL) { printf("OpenDir Error!\n"); exit(1); } while ((myitem = readdir(mydir)) != NULL) { if (sprintf(commd, myitem->d_name, N) < 0) { printf("Sprintf Error!\n"); exit(1); } if (write(sockfd, commd, N) < 0) { printf("Write Error!\n"); exit(1); } } closedir(mydir); close(sockfd); return; } void commd_get(int sockfd, char *filename) { int fd, nbytes; char buffer[N]; bzero(buffer, N); printf("get filename : [ %s ]\n", filename); if ((fd = open(filename, O_RDONLY)) < 0) { printf("Open file Error!\n"); buffer[0] = 'N'; if (write(sockfd, buffer, N) < 0) { printf("Write Error!At commd_get 1\n"); exit(1); } return; } buffer[0] = 'Y'; if (write(sockfd, buffer, N) < 0) { printf("Write Error! At commd_get 2!\n"); close(fd); exit(1); } while ((nbytes = read(fd, buffer, N)) > 0) { if (write(sockfd, buffer, nbytes) < 0) { printf("Write Error! At commd_get 3!\n"); close(fd); exit(1); } } close(fd); close(sockfd); return; } void commd_put(int sockfd, char *filename) { int fd, nbytes; char buffer[N]; bzero(buffer, N); printf("get filename : [ %s ]\n", filename); if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) { printf("Open file Error!\n"); return; } while ((nbytes = read(sockfd, buffer, N)) > 0) { if (write(fd, buffer, nbytes) < 0) { printf("Write Error! At commd_put 1!\n"); close(fd); exit(1); } } close(fd); close(sockfd); return; } |
客户端代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
//client.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <fcntl.h> #define N 256 typedef struct sockaddr SA; void commd_help(); void commd_exit(); void commd_ls(struct sockaddr_in, char *); void commd_get(struct sockaddr_in, char *); void commd_put(struct sockaddr_in, char *); int main(int argc, char *argv[]) { char commd[N]; struct sockaddr_in addr; int len; bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_port = htons(8989); len = sizeof(addr); while (1) { printf("ftp>"); bzero(commd, N); if (fgets(commd, N, stdin) == NULL) { printf("Fgets Error!\n"); return -1; } commd[strlen(commd) - 1] = '\0'; printf("Input Command Is [ %s ]\n", commd); if (strncmp(commd, "help", 4) == 0) { commd_help(); } else if (strncmp(commd, "exit", 4) == 0) { commd_exit(); exit(0); } else if (strncmp(commd, "ls", 2) == 0) { commd_ls(addr, commd); } else if (strncmp(commd, "get", 3) == 0) { commd_get(addr, commd); } else if (strncmp(commd, "put", 3) == 0) { commd_put(addr, commd); } else { printf("Command Is Error!Please Try Again!\n"); } } return 0; } void commd_help() { printf("\n=------------------- Welcome to Use the Ftp ----------------=\n"); printf("| |\n"); printf("| help : Display All Command for the Server |\n"); printf("| |\n"); printf("| exit: Quit The Sever |\n"); printf("| |\n"); printf("| ls : Display All file On the Ftp Server |\n"); printf("| |\n"); printf("| get <file>: Download FIle from the Ftp Server |\n"); printf("| |\n"); printf("| put <file>: Upload FIle to the Ftp Server |\n"); printf("| |\n"); printf("=-----------------------------------------------------------=\n"); return; } void commd_exit() { printf("Byte!\n"); } void commd_ls(struct sockaddr_in addr, char *commd) { int sockfd; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("Socket Error!\n"); exit(1); } if (connect(sockfd, (SA *) & addr, sizeof(addr)) < 0) { printf("Connect Error!\n"); exit(1); } if (write(sockfd, commd, N) < 0) { printf("Write Error!\n"); exit(1); } while (read(sockfd, commd, N) > 0) { printf(" %s ", commd); } printf("\n"); close(sockfd); return; } void commd_get(struct sockaddr_in addr, char *commd) { int fd; int sockfd; char buffer[N]; int nbytes; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("Socket Error!\n"); exit(1); } if (connect(sockfd, (SA *) & addr, sizeof(addr)) < 0) { printf("Connect Error!\n"); exit(1); } if (write(sockfd, commd, N) < 0) { printf("Write Error!At commd_get 1\n"); exit(1); } if (read(sockfd, buffer, N) < 0) { printf("Read Error!At commd_get 1\n"); exit(1); } if (buffer[0] == 'N') { close(sockfd); printf("Can't Open The File!\n"); return; } if ((fd = open(commd + 4, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) { printf("Open Error!\n"); exit(1); } while ((nbytes = read(sockfd, buffer, N)) > 0) { if (write(fd, buffer, nbytes) < 0) { printf("Write Error!At commd_get 2"); } } close(fd); close(sockfd); return; } void commd_put(struct sockaddr_in addr, char *commd) { int fd; int sockfd; char buffer[N]; int nbytes; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("Socket Error!\n"); exit(1); } if (connect(sockfd, (SA *) & addr, sizeof(addr)) < 0) { printf("Connect Error!\n"); exit(1); } if (write(sockfd, commd, N) < 0) { printf("Wrtie Error!At commd_put 1\n"); exit(1); } if ((fd = open(commd + 4, O_RDONLY)) < 0) { printf("Open Error!\n"); exit(1); } while ((nbytes = read(fd, buffer, N)) > 0) { if (write(sockfd, buffer, nbytes) < 0) { printf("Write Error!At commd_put 2"); } } close(fd); close(sockfd); return; } |
不好意思忘写注释了,在这里跟大家分享一下个人收获。在一开始写这个程序时,只要用到自己定义的命令服务端就挂掉了,这个问题困扰许久,后来才发现自己写的代码中对于出错处理时用到的函数是exit(1),而不是用的return。后来把exit(1)改写成return 问题就解决了,后来查资料得出exit()是退出当前的进程,而return 只是退出函数体而并不结束进程。还遇到了另外的一个问题,就是我自己定义的ftp中的命令只能运行一次,第二次运行时就会报connect失败,当服务端先于客户端退出时再次运行服务端时也会出现这样的问题,当过一段时间再次运行时就会解决这个问题,可能是系统回收时有点慢的原因,但是自己的定义命令还是出现同样的问题,后来把套接字的创建和链接都从客户端的主程序中移到了函数中去做了,问题就解决了,这样看来跟服务端先于客户端退出时出现的问题应该是一样的,但是我们的程序不可能停下来等,所以,只能是修改自己的程序来解决这个问题,于是就让每个函数来自己创建套接字使用完后再关闭它,这样问题就解决了。到这我的收获就说完了,如果谁有这方面的体会心得希望能一起分享给大家!!
发表评论
要发表评论,您必须先登录。