⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tftp-client.c

📁 socket编程, 查看server下相应目录的所有文件, 并且可通过tftp下载.
💻 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 + -