代码改变世界

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);    
}