📄 tftpc.c
字号:
/**********************************************************Date: NOV 28th, 2006Project : TFTP ClientProgramers: Jonathan FelskeAndrew Fullard Craig HolmesReza Rahmanian Adam Tomalty File: TFTP Client (main)Purpose: A TFTP client that will request a connections from the server and transefet files.Notes: Here we are using the sendto and recvfrom functions so the server and client can exchange data.***********************************************************/#include "tftp.h"/*a function to print the Help menu*/void help (char *);/*a function to create the request packet, read or write*/int req_packet (int opcode, char *filename, char *mode, char buf[]);/*a function to creat an ACK packet*/int ack_packet (int block, char buf[]);/*a function to create the Error packets*/int err_packet (int err_code, char *err_msg, char buf[]);/*a function that will print the ip:port pair of the server or client, plus data sent or recieved*/void ip_port (struct sockaddr_in host);/*a function to send a file to the server*/void tsend (char *pFilename, struct sockaddr_in server, char *pMode, int sock);/*a function to get a file from the server*/void tget (char *pFilename, struct sockaddr_in server, char *pMode, int sock);/* default values which can be controlled by command line */char path[64] = "/tmp/";int port = 69;unsigned short int ackfreq = 1;int datasize = 512;int debug = 0, w_size = 1, p_length = 512;intmain (int argc, char **argv){ /*local variables */ extern char *optarg; int sock, server_len, len, opt; //,n; char opcode, filename[196], mode[12] = "octet"; struct hostent *host; /*for host information */ struct sockaddr_in server; //, client; /*the address structure for both the server and client */ FILE *fp; /*a pointer to a file that the client will send or get from the server */ if (argc < 2) { help (argv[0]); return 0; } if (!(host = gethostbyname (argv[1]))) { perror ("Client could not get host address information"); exit (2); } /* All of the following deals with command line switches */ while ((opt = getopt (argc, argv, "dnoh:P:p:g:l:w:")) != -1) /* this function is handy */ { switch (opt) { case 'd': /* debug mode (no opts) */ debug = 1; break; case 'P': /* Port (opt required) */ port = atoi (optarg); if (debug) { printf ("Client: The port number is: %d\n", port); } break; case 'p': /* put a file on the server */ strncpy (filename, optarg, sizeof (filename) - 1); opcode = WRQ; fp = fopen (filename, "r"); /*opened the file for reading */ if (fp == NULL) { printf ("Client: file could not be opened\n"); return 0; } if (debug) { printf ("Client: The file name is: %s and can be read", filename); } fclose (fp); break; case 'g': /*get a file from the server */ strncpy (filename, optarg, sizeof (filename) - 1); opcode = RRQ; fp = fopen (filename, "w"); /*opened the file for writting */ if (fp == NULL) { printf ("Client: file could not be created\n"); return 0; } if (debug) { printf ("Client: The file name is: %s and it has been created", filename); } fclose (fp); break; case 'w': /* Get the window size */ ackfreq = atoi (optarg); if (debug) { printf ("Client: Window size is: %i\n", ackfreq); } //ackfreq = atoi (optarg); if (ackfreq > MAXACKFREQ) { printf ("Client: Sorry, you specified an ack frequency higher than the maximum allowed (Requested: %d Max: %d)\n", ackfreq, MAXACKFREQ); return 0; } else if (w_size == 0) { printf ("Client: Sorry, you have to ack sometime.\n"); return 0; } break; case 'l': /* packet length */ datasize = atoi (optarg); if (debug) { printf ("Client: Packet length is: %i bytes\n", datasize); } if (datasize > MAXDATASIZE) { printf ("Client: Sorry, you specified a data size higher than the maximum allowed (Requested: %d Max: %d)\n", datasize, MAXDATASIZE); return 0; } break; case 'h': /* Help (no opts) */ help (argv[0]); return (0); break; case 'o': strncpy (mode, "octet", sizeof (mode) - 1); if (debug) { printf ("Client: The mode is set to octet\n"); } break; case 'n': strncpy (mode, "netascii", sizeof (mode) - 1); if (debug) { printf ("Client: The mode is set to netascii\n"); } break; default: /* everything else */ help (argv[0]); return (0); break; } //end of switch } //end of while loop /*check for valid input*/ if (argc < 5 || argc > 12) { printf ("Client: wrong number of arguments: %d\n", argc); help (argv[0]); exit (ERROR); } /* Done dealing with switches and the command line*/ /*Create the socket, a -1 will show us an error */ if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { printf ("Client: Socket could not be created"); return 0; } /*set the address values for the server */ memset (&server, 0, sizeof (server)); /*Clear the structure */ server.sin_family = AF_INET; /*address family for TCP and UDP */ memcpy (&server.sin_addr, host->h_addr, host->h_length); /*set address of server taken from gethostbyname function */ //server.sin_addr.s_addr = htonl (INADDR_ANY); /*use any address */ server.sin_port = htons (port); /*pick a free port */ server_len = sizeof (server); /*get the length of the server address */ if (debug) printf ("Client: size of server_address is : %d bytes\n", server_len); memset (buf, 0, BUFSIZ); /*clear the buffer */ /* this is the first request message */ len = req_packet (opcode, filename, mode, buf); if (debug) printf ("Client: The request packt's length is: %d bytes\n", len); if (sendto (sock, buf, len, 0, (struct sockaddr *) &server, server_len) != len) { perror ("Client: sendto has returend an error"); exit (ERROR); } if (debug) ip_port (server); switch (opcode) { case RRQ: /*read from the server, download */ tget (filename, server, mode, sock); break; case WRQ: /*write to the server, upload */ tsend (filename, server, mode, sock); break; default: printf ("Invalid opcode detected. Ignoring packet."); } close (sock); /* close the socket */ return 1;} //end of main/****************************************************************** Function deffinitions*******************************************************************//*usage of the command:./tftpc server -P port# -g(get file)|-p(put file) <filename> -w (window size) -l (packetlength)if windowsize and packet length are not chosen then a default value of 1, for thewindow size and 512 bytes for the packet length will be set.*//* a function to display the help menu*/voidhelp (char *app){ printf ("Usage:\n%s server [-h] [-d] [-P port] [-g] | [-p] [file-name] [-w size] [-l length] [-o] [-n]\n", app); printf ("Options:\n-h (help; this message)\n-d (Debug mode)\n-P port(Port number default is 69)\n-g (get a file from the server)\n-p (send a file to the server)\n"); printf ("-w size (set window size, default is 1)\n-l len (set max packet length, default is 512 bytes)\n"); printf ("-o for octet file transfer (default).\n-n for netascii file transfer\n");}/* A function that will create a request packet*//*I'm not sure if I need the last 0x00 because sprintf will end the string with \0*/intreq_packet (int opcode, char *filename, char *mode, char buf[]){ int len; len = sprintf (buf, "%c%c%s%c%s%c", 0x00, opcode, filename, 0x00, mode, 0x00); if (len == 0) { printf ("Error in creating the request packet\n"); /*could not print to the client buffer */ exit (ERROR); } if (debug) { printf ("I am creating the request packet.\n"); } return len;}/* A function that will create an ACK packet*//*problem that we will have here is that we can only get up to 255 blocks*/intack_packet (int block, char buf[]){ int len; len = sprintf (buf, "%c%c%c%c", 0x00, ACK, 0x00, 0x00); buf[2] = (block & 0xFF00) >> 8; buf[3] = (block & 0x00FF); if (len == 0) { printf ("Error in creating the ACK packet\n"); /*could not print to the client buffer */ exit (ERROR); } if (debug) { printf ("I am creating the ACK packet.\n"); } return len;}/* A function that will create an error packet based on the error code*/interr_packet (int err_code, char *err_msg, char buf[]){ int len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -