ftp的简单实现(客户端和服务器端)
2013-05-20 18:58 夏洛克·福尔摩斯 阅读(856) 评论(0) 编辑 收藏 举报1 /***************************************************************** 2 ** File Name:client.c 3 * Author:Maxiao 4 * Date:2003.5.23 5 *****************************************************************/ 6 #include <stdio.h> 7 #include <unistd.h> 8 #include <stdlib.h> 9 #include <limits.h> 10 #include <string.h> 11 #include <ctype.h> 12 #include <sys/types.h> 13 #include <sys/socket.h> 14 #include <netdb.h> 15 #include <netinet/in.h> 16 #include <arpa/inet.h> 17 #include <errno.h> 18 #include <dirent.h> 19 20 #define MAX_INPUT_SIZE 254 21 #define SERVICE_PORT 3482 22 #define FILEBUF_SIZE 1000 23 24 25 unsigned int get(char * filename, char * server); 26 unsigned int put(char * filename, char * server); 27 unsigned int pwd(char * server); 28 unsigned int dir(char * server); 29 unsigned int rcd(char * filename, char * server); 30 void help(); 31 void lpwd(); 32 void ldir(); 33 void lcd(char * filename); 34 35 int main(int argc, char *argv[]) { 36 char line_in[MAX_INPUT_SIZE+1]; 37 unsigned int bytes; 38 39 line_in[0] = '\0'; 40 41 /* Enforce the correct usage */ 42 if (argc != 2) { 43 printf("\nUsage: \"./client ServerName( or IpAddress)\"\n"); 44 exit(1); 45 } 46 47 /* Print a welcome and instructions */ 48 help(); 49 50 printf("\n> "); /* First prompt */ 51 52 while (strncmp("quit", line_in, 4) != 0) { /* As long as "quit" wasn't entered */ 53 fgets(line_in, MAX_INPUT_SIZE, stdin); /* Get the input line */ 54 line_in[strlen(line_in)-1] = '\0'; /* Replace the newline that gets copied */ 55 56 if (strncmp("quit", line_in, 4) != 0) { /* If it's not "quit" */ 57 if (strncmp("put", line_in, 3) == 0) { 58 /* PUT command... */ 59 if ((bytes=put(&(line_in[4]), argv[1]))) { 60 printf("put successful: %d bytes sent to server", bytes); 61 } else { 62 printf("put unsuccessful..."); 63 } 64 } else if (strncmp("get", line_in, 3) == 0) { 65 /* GET command... */ 66 if ((bytes=get(&(line_in[4]), argv[1]))) { 67 printf("get successful: %d bytes retrieved from server", bytes); 68 } else { 69 printf("get unsuccessful... file probably does not exist"); 70 } 71 } else if (strncmp("dir", line_in, 3) == 0) { 72 /* dir command... (remote) */ 73 if (dir(argv[1])==0) { 74 printf("Unable to retrieve remote directory listing!"); 75 } 76 } else if (strncmp("ldir", line_in, 4) == 0) { 77 /* ldir command... (local) */ 78 ldir(); 79 } else if (strncmp("lpwd", line_in, 3) == 0) { 80 /* lpwd command... (local) */ 81 lpwd(); 82 } else if (strncmp("?", line_in, 1) == 0) { 83 /* ? command... (local) */ 84 help(); 85 } else if (strncmp("pwd", line_in, 3) == 0) { 86 /* pwd command... (remote) */ 87 if (pwd(argv[1])==0) { 88 printf("Unable to retrieve remote directory listing!"); 89 } 90 } else if (strncmp("rcd", line_in, 3) == 0) { 91 /* rcd command... (remote)*/ 92 if ((bytes=rcd(&(line_in[4]), argv[1]))) { 93 printf("get unsuccessful.", bytes); 94 } else { 95 printf(&(line_in[4])); 96 } 97 } else if (strncmp("lcd", line_in, 3) == 0) { 98 /* lcd command... (local)*/ 99 lcd(&(line_in[4])) ; 100 101 } else { 102 printf("Unrecognized command!"); 103 } 104 printf("\n> "); /* Next prompt */ 105 } 106 } 107 108 exit(0); 109 } 110 111 /*show the help info*/ 112 void help() { 113 printf("\nWelcome to FTP program client!\n"); 114 printf("Valid commands are (case sensitive):\n"); 115 printf("\tget\t\tPlaces a remote file in the local directory\n"); 116 printf("\tput\t\tPlaces a local file in the remote directory\n"); 117 printf("\tpwd\t\tLists a remote current directory\n"); 118 printf("\tdir\t\tLists the contents of the remote directory\n"); 119 printf("\trcd\t\tChange a remote current directory\n"); 120 printf("\t?\t\tFor help\n"); 121 printf("\tquit\t\tExits the program\n"); 122 printf("\tlpwd\t\tLists a local current directory\n"); 123 printf("\tldir\t\tLists the contents of the local directory\n"); 124 printf("\tlcd\t\tChange client current directory\n"); 125 } 126 127 /*Places a local file in the remote directory*/ 128 unsigned int put(char * filename, char * server) { 129 int sck; 130 struct sockaddr_in serv_adr; 131 struct hostent *host; 132 FILE *infile; 133 unsigned char databuf[FILEBUF_SIZE]; 134 int bytes = 0, bytesread = 0; 135 136 /* Open the file locally */ 137 if ((infile = fopen(filename, "r")) == 0) { 138 perror("fopen failed to open file"); 139 return 0; 140 } 141 142 /* Attempt to get the IP for the server by hostname */ 143 host = gethostbyname(server); 144 if (host == (struct hostent *) NULL) { 145 perror("gethostbyname failed"); 146 return 0; 147 } 148 149 /* Setup the port for the connection */ 150 memset(&serv_adr, 0, sizeof(serv_adr)); 151 serv_adr.sin_family = AF_INET; 152 memcpy(&serv_adr.sin_addr, host->h_addr, host->h_length); 153 serv_adr.sin_port = htons(SERVICE_PORT); 154 155 /* Get the socket */ 156 if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 157 perror("error on socket()"); 158 return 0; 159 } 160 161 /* Connect to the server */ 162 if (connect(sck, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) < 0) { 163 perror("error on connect()"); 164 return 0; 165 } 166 167 /* Write the command & filename, followed by two newlines */ 168 write(sck, "PUT ", 4); 169 write(sck, filename, strlen(filename)); 170 write(sck, "\n\n", 2); 171 172 /* Read from the file and write to the socket */ 173 while ((bytes = read(fileno(infile), databuf, FILEBUF_SIZE)) > 0) { 174 write(sck, databuf, bytes); 175 bytesread += bytes; 176 } 177 178 /* Close the file */ 179 fclose(infile); 180 181 if ((bytes = read(sck, databuf, 2)) > 0) { 182 /* Read the status bytes from the server, print and return accordingly */ 183 if ((databuf[0] == 'E') && (databuf[1] == 'R')) { 184 printf("Server error on PUT!\n"); 185 close(sck); 186 return 0; 187 } else if ((databuf[0] == 'N') && (databuf[1] == 'W')) { 188 printf("File created on server\n"); 189 close(sck); 190 return bytesread; 191 } else if ((databuf[0] == 'U') && (databuf[1] == 'P')) { 192 printf("File updated on server\n"); 193 close(sck); 194 return bytesread; 195 } 196 } else return 0; 197 } 198 199 /*Places a remote file in the local directory*/ 200 unsigned int get(char * filename, char * server) { 201 int sck; 202 struct sockaddr_in serv_adr; 203 struct hostent *host; 204 FILE *outfile; 205 short file_open=0; 206 unsigned char databuf[FILEBUF_SIZE]; 207 int bytes = 0, bytesread = 0; 208 209 /* Attempt to get the IP for the server by hostname */ 210 host = gethostbyname(server); 211 if (host == (struct hostent *) NULL) { 212 perror("gethostbyname failed"); 213 return 0; 214 } 215 216 /* Setup the port for the connection */ 217 memset(&serv_adr, 0, sizeof(serv_adr)); 218 serv_adr.sin_family = AF_INET; 219 memcpy(&serv_adr.sin_addr, host->h_addr, host->h_length); 220 serv_adr.sin_port = htons(SERVICE_PORT); 221 222 /* Get the socket */ 223 if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 224 perror("error on socket()"); 225 return 0; 226 } 227 228 /* Connect to the server */ 229 if (connect(sck, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) < 0) { 230 perror("error on connect()"); 231 return 0; 232 } 233 234 /* Write the command & filename, followed by two newlines */ 235 write(sck, "GET ", 4); 236 write(sck, filename, strlen(filename)); 237 write(sck, "\n\n", 2); 238 239 /* Read from the socket and write to the file */ 240 while ((bytes = read(sck, databuf, FILEBUF_SIZE)) > 0) { 241 if (file_open == 0) { 242 /* Open the file the first time we actually read data */ 243 if ((outfile = fopen(filename, "w")) == 0) { 244 perror("fopen failed to open file"); 245 close(sck); 246 return 0; 247 } 248 file_open = 1; 249 } 250 write(fileno(outfile), databuf, bytes); 251 bytesread += bytes; 252 } 253 254 /* Close the file and socket */ 255 if (file_open != 0) fclose(outfile); 256 close(sck); 257 258 return bytesread; 259 } 260 261 /*Lists the contents of the remote directory*/ 262 unsigned int dir(char * server) { 263 int sck; 264 struct sockaddr_in serv_adr; 265 struct hostent *host; 266 unsigned char databuf[FILEBUF_SIZE]; 267 int bytes = 0, bytesread = 0; 268 269 /* Attempt to get the IP for the server by hostname */ 270 host = gethostbyname(server); 271 if (host == (struct hostent *) NULL) { 272 perror("gethostbyname failed"); 273 return 0; 274 } 275 276 /* Setup the port for the connection */ 277 memset(&serv_adr, 0, sizeof(serv_adr)); 278 serv_adr.sin_family = AF_INET; 279 memcpy(&serv_adr.sin_addr, host->h_addr, host->h_length); 280 serv_adr.sin_port = htons(SERVICE_PORT); 281 282 /* Get the socket */ 283 if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 284 perror("error on socket()"); 285 return 0; 286 } 287 288 /* Connect to the server */ 289 if (connect(sck, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) < 0) { 290 perror("error on connect()"); 291 return 0; 292 } 293 294 /* Write the command followed by two newlines */ 295 write(sck, "DI\n\n", 4); 296 297 printf("Remote directory listing:\n"); 298 299 /* Read from the socket and write to stdout */ 300 while ((bytes = read(sck, databuf, FILEBUF_SIZE)) > 0) { 301 write(fileno(stdout), databuf, bytes); 302 bytesread += bytes; 303 } 304 305 close(sck); /* Close the socket */ 306 307 return bytesread; 308 } 309 310 /*ists the contents of the local directory*/ 311 void ldir() { 312 FILE *fcmd; 313 char buffer[PIPE_BUF]; 314 int n; 315 316 printf("Local directory listing:\n"); 317 318 /* Open the pipe to the ls command */ 319 if ((fcmd = popen("ls -l", "r")) == 0) { 320 perror("popen error"); 321 return; 322 } 323 324 /* Read from the pipe and write to stdout */ 325 while ((n = read(fileno(fcmd), buffer, PIPE_BUF)) > 0) 326 write(fileno(stdout), buffer, n); 327 328 /* Close the pipe */ 329 if (pclose(fcmd) != 0) { 330 printf("Non-zero return value from \"ldir\""); 331 } 332 } 333 334 /*Lists a local current directory*/ 335 unsigned int pwd(char * server) { 336 int sck; 337 struct sockaddr_in serv_adr; 338 struct hostent *host; 339 unsigned char databuf[FILEBUF_SIZE]; 340 int bytes = 0, bytesread = 0; 341 342 /* Attempt to get the IP for the server by hostname */ 343 host = gethostbyname(server); 344 if (host == (struct hostent *) NULL) { 345 perror("gethostbyname failed"); 346 return 0; 347 } 348 349 /* Setup the port for the connection */ 350 memset(&serv_adr, 0, sizeof(serv_adr)); 351 serv_adr.sin_family = AF_INET; 352 memcpy(&serv_adr.sin_addr, host->h_addr, host->h_length); 353 serv_adr.sin_port = htons(SERVICE_PORT); 354 355 /* Get the socket */ 356 if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 357 perror("error on socket()"); 358 return 0; 359 } 360 361 /* Connect to the server */ 362 if (connect(sck, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) < 0) { 363 perror("error on connect()"); 364 return 0; 365 } 366 367 /* Write the command followed by two newlines */ 368 write(sck, "PW\n\n", 4); 369 370 371 printf("Remote directory listing:\n"); 372 373 /* Read from the socket and write to stdout */ 374 while ((bytes = read(sck, databuf, FILEBUF_SIZE)) > 0) { 375 376 write(fileno(stdout), databuf, bytes); 377 bytesread += bytes; 378 } 379 380 close(sck); /* Close the socket */ 381 382 return bytesread; 383 } 384 void lpwd() { 385 FILE *fcmd; 386 char buffer[PIPE_BUF]; 387 int n; 388 389 printf("Local directory listing:\n"); 390 391 /* Open the pipe to the ls command */ 392 if ((fcmd = popen("pwd", "r")) == 0) { 393 perror("popen error"); 394 return; 395 } 396 397 /* Read from the pipe and write to stdout */ 398 while ((n = read(fileno(fcmd), buffer, PIPE_BUF)) > 0) 399 write(fileno(stdout), buffer, n); 400 401 /* Close the pipe */ 402 if (pclose(fcmd) != 0) { 403 printf("Non-zero return value from \"lpwd\""); 404 } 405 } 406 407 unsigned int rcd(char * filename, char * server) { 408 int sck; 409 struct sockaddr_in serv_adr; 410 struct hostent *host; 411 unsigned char databuf[FILEBUF_SIZE]; 412 int bytes = 0, bytesread = 0; 413 414 /* Attempt to get the IP for the server by hostname */ 415 host = gethostbyname(server); 416 if (host == (struct hostent *) NULL) { 417 perror("gethostbyname failed"); 418 return 0; 419 } 420 421 /* Setup the port for the connection */ 422 memset(&serv_adr, 0, sizeof(serv_adr)); 423 serv_adr.sin_family = AF_INET; 424 memcpy(&serv_adr.sin_addr, host->h_addr, host->h_length); 425 serv_adr.sin_port = htons(SERVICE_PORT); 426 427 /* Get the socket */ 428 if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 429 perror("error on socket()"); 430 return 0; 431 } 432 433 /* Connect to the server */ 434 if (connect(sck, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) < 0) { 435 perror("error on connect()"); 436 return 0; 437 } 438 439 /* Write the command followed by two newlines */ 440 write(sck, "RC ", 4); 441 write(sck, filename, strlen(filename)); 442 write(sck, "\n\n", 2); 443 444 printf("Current remote directory has changed, now is :\n"); 445 446 /* Read from the socket and write to stdout */ 447 while ((bytes = read(sck, databuf, FILEBUF_SIZE)) > 0) { 448 write(fileno(stdout), databuf, bytes); 449 bytesread += bytes; 450 } 451 452 close(sck); /* Close the socket */ 453 454 return bytesread; 455 } 456 457 void lcd(char * filename) { 458 FILE *fcmd; 459 char buffer[PIPE_BUF]; 460 int n; 461 chdir(filename); 462 printf("Current client directory has changed ,now is:\n"); 463 printf(filename); 464 printf("\n"); 465 466 }
/***************************************************************** ** File Name:server.c * Author:Maxiao * Date:2003.5.23 *****************************************************************/ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <limits.h> #include <string.h> #include <ctype.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/stat.h> #include <netdb.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <dirent.h> #define MAX_INPUT_SIZE 254 #define SERVICE_PORT 3482 #define FILEBUF_SIZE 1000 void get(char * filename, int sck); void put(char * filename, int sck); void rcd(char * filename, int sck); void dir(int sck); void pwd(int sck); int main(int argc, char *argv[]) { char buffer[FILEBUF_SIZE]; int sck, clnt_sck; int clnt_len; int i = 0; int opt; struct sockaddr_in serv_adr, clnt_adr; printf("\nWelcome to FTP program server!\n"); /* Get the socket */ if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("error on socket()"); exit(1); } /* This is to avoid the 120-second timeout on the port when the server is killed */ opt = 1; if (setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0) { perror("setsockopt error"); exit(2); } /* Configure the server address, port, etc. */ memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family = AF_INET; serv_adr.sin_addr.s_addr = htonl(INADDR_ANY); serv_adr.sin_port = htons(SERVICE_PORT); /* Bind this port to this process */ if (bind(sck, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) < 0) { perror("bind error"); exit(3); } /* Listen on this port for incoming connections */ if (listen(sck, 5) < 0) { perror("listen error"); exit(4); } /* Infinite loop */ while (1) { i=0; clnt_len = sizeof(clnt_adr); /* Accept an incoming request */ if ((clnt_sck = accept(sck, (struct sockaddr *) &clnt_adr, &clnt_len)) < 0) { perror("accept error"); close(sck); exit(5); } /* Get the first two bytes to see what it is */ read(clnt_sck, buffer, 2); if ((buffer[0] == 'G') && (buffer[1] == 'E')) { /* It's a GET */ read(clnt_sck, buffer, 2); /* Consume the "T " */ read(clnt_sck, buffer, 2); /* Start reading the filename */ /* Read until we get a newline or two */ while ((buffer[i] != '\n') && (buffer[i+1] != '\n')) { i += 2; read(clnt_sck, &buffer[i], 2); } /* If we only got one newline, consume the second, then place the null in the proper place */ if (buffer[i] == '\n') buffer[i] = '\0'; else { read(clnt_sck, &buffer[i+1], 1); buffer[i+1] = '\0'; } get(buffer, clnt_sck); /* Do the actual GET */ } else if ((buffer[0] == 'P') && (buffer[1] == 'U')) { /* It's a PUT */ read(clnt_sck, buffer, 2); /* Consume the "T " */ read(clnt_sck, buffer, 2); /* Start reading the filename */ /* Read until we get a newline or two */ while ((buffer[i] != '\n') && (buffer[i+1] != '\n')) { i += 2; read(clnt_sck, &buffer[i], 2); } /* If we only got one newline, consume the second, then place the null in the proper place */ if (buffer[i] == '\n') buffer[i] = '\0'; else { read(clnt_sck, &buffer[i+1], 1); buffer[i+1] = '\0'; } put(buffer, clnt_sck); /* Do the actual PUT */ } else if ((buffer[0] == 'R') && (buffer[1] == 'C')) { /* It's a PUT */ read(clnt_sck, buffer, 2); /* Consume the "T " */ read(clnt_sck, buffer, 2); /* Start reading the filename */ /* Read until we get a newline or two */ while ((buffer[i] != '\n') && (buffer[i+1] != '\n')) { i += 2; read(clnt_sck, &buffer[i], 2); } /* If we only got one newline, consume the second, then place the null in the proper place */ if (buffer[i] == '\n') buffer[i] = '\0'; else { read(clnt_sck, &buffer[i+1], 1); buffer[i+1] = '\0'; } rcd(buffer, clnt_sck); /* Do the actual PUT */ } else if ((buffer[0] == 'D') && (buffer[1] == 'I')) { /* It's an LS */ read(clnt_sck, buffer, 2); /* Consume the two newlines */ dir(clnt_sck); /* Perform the LS */ } else if ((buffer[0] == 'P') && (buffer[1] == 'W')) { /* It's an LS */ read(clnt_sck, buffer, 2); /* Consume the two newlines */ pwd(clnt_sck); /* Perform the LS */ } close(clnt_sck); /* Close the incoming client connection */ } exit(0); /* This will never happen */ } void put(char * filename, int sck) { FILE *outfile; unsigned char databuf[FILEBUF_SIZE]; struct stat sbuf; int bytes = 0; char return_code[2]; /* stat() the file to see if it's an update or create */ if (stat(filename, &sbuf) == -1) { return_code[0] = 'N'; return_code[1] = 'W'; } else { return_code[0] = 'U'; return_code[1] = 'P'; } /* Return the appropriate status code */ write(sck, return_code, 2); if ((outfile = fopen(filename, "w")) == 0) { perror("fopen failed to open file"); /* Return the error status code */ return_code[0] = 'E'; return_code[1] = 'R'; write(sck, return_code, 2); return; } /* Read the incoming bytes and write to the file */ while ((bytes = read(sck, databuf, FILEBUF_SIZE)) > 0) write(fileno(outfile), databuf, bytes); /* Close the file */ fclose(outfile); } void get(char * filename, int sck) { FILE *infile; unsigned char databuf[FILEBUF_SIZE]; int bytes = 0; /* Open up the file locally */ if ((infile = fopen(filename, "r")) == 0) { perror("fopen failed to open file"); return; } /* Read from the file and write the bytes to the socket */ while ((bytes = read(fileno(infile), databuf, FILEBUF_SIZE)) > 0) write(sck, databuf, bytes); /* Close the file */ fclose(infile); } /* Read from the file and write the bytes to the socket */ void dir(int sck) { FILE *fcmd; char buffer[PIPE_BUF]; int n; /* Open the pipe to the ls -l command */ if ((fcmd = popen("ls -l", "r")) == 0) { perror("popen error"); return; } /* Read from the pipe and write to the socket */ while ((n = read(fileno(fcmd), buffer, PIPE_BUF)) > 0) write(sck, buffer, n); /* Close the pipe - we should never get a non-zero return from ls */ if (pclose(fcmd) != 0) { printf("Non-zero return value from \"ls -l\""); } } void pwd(int sck) { FILE *fcmd; char buffer[PIPE_BUF]; int n; /* Open the pipe to the ls -l command */ if ((fcmd = popen("pwd", "r")) == 0) { perror("popen error"); return; } /* Read from the pipe and write to the socket */ while ((n = read(fileno(fcmd), buffer, PIPE_BUF)) > 0) write(sck, buffer, n); /* Close the pipe - we should never get a non-zero return from ls */ if (pclose(fcmd) != 0) { printf("Non-zero return value from \"ls -l\""); } } void rcd(char *filename, int sck) { FILE *fcmd; char buffer[PIPE_BUF]; int n; chdir(filename); }
技术成就现在,眼光着看未来。