📄 tftp-client.c
字号:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
/*******************************************
* Structure declarations for the format
* of the TFTP list system
******************************************/
struct tftp_list
{
unsigned short id_Number;
char TFTPlist_type;
char TFTPlist_ack;
unsigned short block_Number;
char TFTPlist_cmd[4];
};
/*******************************************
* This function reports the error and
* exits back to the shell :
******************************************/
static void bail(const char *on_what)
{
fputs(strerror(errno),stderr);
fputs(": ",stderr);
fputs(on_what,stderr);
fputc('\n',stderr);
exit(1);
}
/******************************************
* this is the download file function
*****************************************/
void getfile (char *server_address)
{
FILE *fileListIn;
char *ListFileName="LIST.TXT";
char FILENUM[100],CMD[100];
char NUM[100];
char cChar, fileName[512];
int iExit = 0, i=0, z = 0;
if((fileListIn=fopen(ListFileName, "r")) ==NULL)
printf ("Open file error\n");
memset (FILENUM,0,100);
memset (fileName,0,512);
memset (NUM,0,100);
memset (CMD,0,100);
NUM[0] = '1';
printf ("Whitch file you want to download? \nPlease input the number...\n");
scanf("%s",FILENUM);
// printf ("%s\n",FILENUM);
cChar = fgetc(fileListIn);
cChar = fgetc(fileListIn);
if (strcmp (NUM,FILENUM) == 0)
{
for (;;)
{
cChar = fgetc(fileListIn);
if (cChar == '\n')
{
goto END;
}else{
fileName[i] = cChar;
}
i++;
}
goto END;
}
START:
for (;;)
{
z = 0; i = 0;
cChar = fgetc(fileListIn);
if (cChar == '\n')
{
for (;;)
{
cChar = fgetc(fileListIn);
if (cChar == '\t')
{ goto GETFILENAME;
}else{
NUM[z] = cChar;
}
z++;
}
}
GETFILENAME:
if (strcmp (NUM,FILENUM) != 0)
{ goto START;}
if (cChar == '\t')
{
for (;;)
{
cChar = fgetc(fileListIn);
if (cChar == '\n')
{
goto END;
}else{
fileName[i] = cChar;
}
i++;
}
}
}
END:
// printf ("%s\t",NUM);
printf ("\nFile %s is downloading\n",fileName);
printf ("\n");
#ifdef WIN32
sprintf (CMD, "tftp -i %s get %s",server_address,fileName);
#else
sprintf (CMD, "tftp -v %s -c get %s",server_address,fileName);
#endif
printf ("%s\n",CMD);
system (CMD);
fclose (fileListIn);
}
/*******************************************
* Function to print a frame
* arguments include:
* STRUCT frame type
******************************************/
int print_frame( struct tftp_list *frame )
{
unsigned short i;
printf("[%d]", frame->id_Number);
printf("[%c]", frame->TFTPlist_type);
printf("[%c]", frame->TFTPlist_ack);
printf("[%d]", frame->block_Number);
printf("[");
for(i=0; i<4;i++) printf("%c", frame->TFTPlist_cmd[i]);
printf("]\n");
return (0);
}
/*******************************************
* this is the main body of the program with
* a simple state machine
******************************************/
int main(int argc,char **argv)
{
int z, iLoop, whileLoop;
char cBuf1[512],cBuf2[512];
int RxSocket, TxSocket;
struct sockaddr_in server_address, client_address;
char *srvr_addr = "IPADDR_ANY";
char *clet_addr = "IPADDR_ANY";
char *ListFileName="LIST.TXT";
unsigned int addr_len;
unsigned short srvr_port = 6969, iExit;
unsigned long non_blocking = 1, blocking = 0;
FILE *fileListIn;
struct tftp_list *ptrFrame;
time_t CurrentTime, CheckTime;
//Server and Client Address
srvr_addr = "192.168.0.203";
clet_addr = "192.168.0.200";
//get the Server and Client address from CMD line
if( argc >= 4 )
{
srvr_addr = argv[2];
clet_addr = argv[3];
}
else {
argv[1] = "UDP";
printf("\n---------------------------------------------------------\n");
printf ("Usage: ./TFTP-Client [TCP|UDP] <Server Address> <Client Address>\n");
printf ("The program defaults to UDP Port 6969\n");
printf("---------------------------------------------------------\n\n");
// exit (0);
}
printf("\nServer Address : %s Client Address : %s Port : %d\n",
srvr_addr,clet_addr, srvr_port );
//-------------------------------------------------------------
//For Windows WSASTARTUP ( )
#ifdef WIN32
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
{
printf ("WSAStartup() failed: %d\n",GetLastError() );
exit (1);
}
}
#endif
//-------------------------------------------------------------
//setting TX socket in here - Blocking
memset( &server_address, 0, sizeof server_address);
memset( &client_address, 0, sizeof client_address);
addr_len = sizeof(server_address);
//Set the Address family
server_address.sin_family = AF_INET;
server_address.sin_port = htons(srvr_port);
server_address.sin_addr.s_addr = inet_addr(srvr_addr);
client_address.sin_family = AF_INET;
client_address.sin_port = htons(srvr_port);
client_address.sin_addr.s_addr = inet_addr(clet_addr);
//Create Socket --UDP/TCP
if ( strcmp (argv[1],"TCP") == 0)
{
//Create Socket -- TCP
RxSocket = socket(PF_INET,SOCK_STREAM, 0);
if(RxSocket == -1) bail("02 error in creating a RX TCP socket");
}else{
//Create TxSocket -- UDP
TxSocket = socket(AF_INET,SOCK_DGRAM,0);
if(TxSocket == -1) bail("01 error in creating a TX UDP socket");
//Create RxSocket -- UDP
RxSocket = socket(AF_INET,SOCK_DGRAM, 0);
if(RxSocket == -1) bail("02 error in creating a RX UDP socket");
}
//bind the RxSocket
z = bind(RxSocket, (struct sockaddr *)&client_address, addr_len);
if(z == -1) bail("03 could not bind to address and port");
//Create the frame
/*The structure of the Frame
----------------------------------------
| RMD No.| U | | Block Number | LIST |
----------------------------------------
*/
memset( &cBuf1, 0, sizeof cBuf1);
ptrFrame = (struct tftp_list *) &cBuf1;
srand ( (unsigned)time(NULL) );
ptrFrame->id_Number = rand ( ); //get a RMD number
if ( strcmp (argv[1],"TCP") == 0)
{
ptrFrame->TFTPlist_type = 'T'; // TCP Connection
}else{
ptrFrame->TFTPlist_type = 'U'; // UDP connection
}
ptrFrame->TFTPlist_ack = ' ';
ptrFrame->block_Number = 0;
ptrFrame->TFTPlist_cmd[0] = 'L';
ptrFrame->TFTPlist_cmd[1] = 'I';
ptrFrame->TFTPlist_cmd[2] = 'S';
ptrFrame->TFTPlist_cmd[3] = 'T';
if ( strcmp (argv[1],"TCP") != 0)
{
printf ("BLOCKING\n");
//Set the Non-Blocking Mode
#ifdef WIN32
ioctlsocket (RxSocket, FIONBIO, &non_blocking);
#else
{
long lFlags, lFlagsOld;
lFlagsOld = fcntl(RxSocket, F_GETFL);
lFlags = lFlagsOld;
lFlags |= O_NONBLOCK;
if(fcntl(RxSocket, F_SETFL, lFlags)==-1 )
bail("04 error setting RX flags");
}
#endif
}
//Disthe Send frame on the screen
printf ("---------------------------------------\n");
printf ("Tx REQ Frame: \t"); print_frame (ptrFrame);
printf ("---------------------------------------\n");
//If TCP, Connect to server
if ( strcmp (argv[1],"TCP") == 0)
{
int TCP_Conn = connect (RxSocket, (struct sockaddr *)&server_address, addr_len);
if (TCP_Conn == -1) bail ("TCP Connect to server error\n");
//send the Requirment Frame with LIST CMD to Server
//if TCP connection
z = send (RxSocket,cBuf1,22,0);
if ( z == -1 ) bail ("05 Send the first requirment Frame error -- TCP\n");
printf ("sent finished\n");
}else{
//if UDP
z = sendto ( TxSocket, cBuf1,22, 0, (struct sockaddr *)&server_address, addr_len);
if ( z == -1 ) bail ("05 Send the first requirment Frame error -- UDP\n");
}
//------------------------Send frame finish------------------
//Wait for 2 seconds for an ACK else EXIT
time(&CheckTime);
z=-1; iLoop=0;
memset(&cBuf2,0,sizeof cBuf2);
ptrFrame = (struct tftp_list *) &cBuf2[0];
while ( ((CheckTime+2) > time(&CurrentTime)) && (z==(-1)) )
{
// if TCP
if ( strcmp (argv[1],"TCP") == 0)
{
z = recv (RxSocket,cBuf2,22,0);
}else{
// if UDP
z = recvfrom(RxSocket,cBuf2,22,0,(struct sockaddr *)&client_address, &addr_len);
}
}
if (z == -1) bail ("06 Receive ACK Timeout--Not received an ACK Frame.\n");
//Display receive frame
ptrFrame = (struct tftp_list *) &cBuf2;
printf ("\nRx ACK Frame: \t"); print_frame (ptrFrame);
printf ("---------------------------------------\n");
//Check the frame
if ((ptrFrame->block_Number != 0) || (ptrFrame->TFTPlist_ack != 'A'))
{
printf ("\tBlock Number on ACK does not match or ACK is not in frame\n");
printf ("\tBlock Number should be 0 and it is %d\n",ptrFrame->block_Number);
return 0;
}
//Open a file to save the List
if ( (fileListIn = fopen(ListFileName,"w")) == NULL)
bail ("07 Can not open file to save list\n");
printf ("\nList is starting to receive, Please wait......\n");
iExit = 0; whileLoop = 0;
//Loop to receive the LIST
while ( !iExit )
{
whileLoop ++;
//Clear the recv buffer
memset (&cBuf1,0,sizeof cBuf1);
//Wait for 2 seconds for recv frame
time(&CheckTime);
z=-1; iLoop=0;
while ( ((CheckTime+2) > time(&CurrentTime)) && (z==(-1)) )
{
//if TCP
if ( strcmp (argv[1],"TCP") == 0)
{
z = recv (RxSocket,cBuf1,512,0);
}else{
//if UDP
z = recvfrom(RxSocket, cBuf1, 512, 0, (struct sockaddr *)&client_address, &addr_len );
}
}
if ( z == -1 ) bail ("08 Recevie LIST Timeout--Can not receive LIST\n");
ptrFrame = (struct tftp_list *) &cBuf1;
//if the final frame received -- Block Number is 65535
if (ptrFrame->block_Number == 65535)
{
printf ("\n------LIST is Finished------\n");
iExit = 1;
break;
}
//check the Block Number and ACK correct
if ((ptrFrame->block_Number != whileLoop) || (ptrFrame->TFTPlist_ack != ' '))
{
printf ("\tBlock Number on ACK does not match or ACK in frame\n");
printf ("\tBlock Number should be %d and it is %d\n",
whileLoop, ptrFrame->block_Number);
iExit = 1;
break;
}
printf ("\n---------------------------------------\n");
printf ("Rx LIST Frame - %d: \t", ptrFrame->block_Number); print_frame (ptrFrame);
printf ("---------------------------------------\n\n");
printf ("Number\tFile_Name\n\n");
//display the LIST on the screen and save them to the file...
for (iLoop = 10; iLoop<512; iLoop++)
{
printf ("%c",cBuf1[iLoop]);
if ( cBuf1[iLoop] != EOF )
{
fputc (cBuf1[iLoop], fileListIn);
}else{
//file EOF, exit the FOR loop
fputc (cBuf1[iLoop], fileListIn);
iLoop = 513;
}
}
//after a LIST frame received, client send a ACK back
ptrFrame->TFTPlist_ack = 'A';
//if TCP
if ( strcmp (argv[1],"TCP") == 0)
{
z = send (RxSocket,cBuf1,22,0);
if (z == -1) bail ("09 Send LIST ACK error -- TCP\n");
}else{
//if UDP
z = sendto ( TxSocket, cBuf1,22, 0, (struct sockaddr *)&server_address, addr_len);
if (z == -1) bail ("09 Send LIST ACK error\n");
}
}
fclose (fileListIn);
#ifdef WIN32
WSACleanup();
#else
{
close (RxSocket);
close (TxSocket);
}
#endif
printf ("\r\n");
getfile(srvr_addr);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -