FTP Project

C++ Source Files in the Project:

server.cpp | client.cpp | administration.cpp | item_record.cpp

C++ Header Files in the Project:

item_record.h

 

 
//======================================================================
//  By Xuan Sun 
//  Dec. 22, 99
//  File: client.cpp
//  Description: This is a FTP client. It requests connection the
//		server, and being handed over to a thread (without knowing it).
//		It receives a data file from the thread, as if a customer gets   	
//		a menu when entering a restuarant. This data file contains a 
//		list of files and folders that are available for people to
//		download and upload to.
//		An array of objects, itemRecord, are generated from this 
//		data file. They are use all through the file transfer process.
//		Clients communicate with the server what they want to do 
//		by sending the index number of this array.
//======================================================================= 

#include windows.h    // not able to use brackets because of HTML tags
#include stdio.h 
#include string.h
#include stdlib.h
#include time.h
#include "item_record.h"

void upload(SOCKET &);
void download(SOCKET &);
void create(void);
void retrieve(void);
void display(SOCKET &);
void load(int, SOCKET &);

char loadDir[50];	// used in upload and download functions
itemRecord currItem;	// the item that is being processed
itemRecord items[11];

void main()
{
	//====================================================
	//	START:	Initialize Socket Info
	//====================================================
	char ipAddrServer[16];
	struct sockaddr_in ClientAddr, ServerAddr;
	int ServerSize=sizeof(sockaddr_in);
	int err;
	WORD wVersionRequested;
	WSADATA	wsaData;
	SOCKET s;
	//====================================================
	//	END:	Initialize Socket Info
	//====================================================

	printf("Please enter the IP address of the server: ");
	gets(ipAddrServer);

	//====================================================
	//	START:	Prepare Socket 
	//====================================================
	wVersionRequested = MAKEWORD( 1,1);
	if (WSAStartup(wVersionRequested, &wsaData)!=0) {
		printf("In WSAStartup, CLIENT Error: %d\n",WSAGetLastError());
		exit(1);
	}

	s=socket(AF_INET, SOCK_STREAM, 0);
	if (s==INVALID_SOCKET){
		printf("In socket, CLIENT  Error: %d\n",WSAGetLastError());
		exit(2);
	}

	ClientAddr.sin_family=AF_INET;
	ClientAddr.sin_addr.s_addr=htonl(INADDR_ANY);
	ClientAddr.sin_port=htons(0);

	if(bind(s,(struct sockaddr *)&ClientAddr,sizeof(sockaddr_in))==SOCKET_ERROR) {
		printf("In bind, CLIENT  Error: %d\n",WSAGetLastError());
		exit(3);
	}
	
	ServerAddr.sin_family=AF_INET;
	ServerAddr.sin_addr.s_addr=inet_addr(ipAddrServer);
	ServerAddr.sin_port=htons(6000);

	err=connect(s, (struct sockaddr *)&ServerAddr,sizeof(sockaddr_in));
	if (err==SOCKET_ERROR) {
		printf("In connect, CLIENT  Error: %d\n",WSAGetLastError());
		exit(4);
	}
	//====================================================
	//	END:	Prepare Socket 
	//====================================================
	

	printf(" The server is connected.\n");

	//to download record file from the server
	strcpy(loadDir,"record.txt");
	download(s);

	//initialize record list
	create();
	//read list from file
	retrieve();
	//display records
	printf("\n\nThis program is ready to do file transfer now\n");
	printf("There are some facts which are helpful to know:\n");
	printf("1. File name size and file directory size should be less than 50.\n");
	printf("2. Blanks in file names and directories are not allowed.\n");
	printf("Advanturous acts beyond these rules may cause the program to abort.\n");
	printf("Soon you'll see the list of files you can download, and folders you can upload to.\n");
	printf("They are displayed one by one. Options to process will be provided after each one.\n");
	printf("Please key in your choice as INSTRUCTED.\n");
	display(s);

	printf("Thank you for using this program.\nHave a brilliant day!\n");

	Sleep(500);
	closesocket(s);
	WSACleanup();
}

	//====================================================
	//	START:	Download Function 
	//	Please refer to the documentation of
	//	upload function in server.cpp
	//====================================================
void download(SOCKET &downloadSocket)
{
	HANDLE writetofile;
	char moveBuffer[1100];
	char sNumRead[3], *stopString;	// for converting from char[] to ul
	unsigned long numRead, numWritten;
	int j=3, counter=0, err;
	double i;

	writetofile=CreateFile(
		loadDir,
		GENERIC_WRITE,
		FILE_SHARE_READ,
		NULL,
		OPEN_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (writetofile==INVALID_HANDLE_VALUE) {
		printf("in WRITEHANDLE error: %d.\n", GetLastError);
		exit(2);
	}
	//=========================================

	do{
		// recv how long the next buffer is
		err=recv(downloadSocket,sNumRead, j,0);
		if (err==SOCKET_ERROR) {
			printf("In recv numRead, THREAD Error: %d\n",WSAGetLastError());
			getchar();
			exit(6);
		}

		i=strtod(sNumRead, &stopString);
		numRead = strtoul( sNumRead, &stopString, 10 );

		if (numRead!=0) {
			// recv buffer from the server
			err=recv(downloadSocket, moveBuffer, numRead,0);
			if (err==SOCKET_ERROR) {
				printf("In recv numRead, THREAD Error: %d\n",WSAGetLastError());
				getchar();
				exit(7);
			}

			// write buffer to the local file
			err=WriteFile(
				writetofile,
				moveBuffer,	
				numRead,
				&numWritten,
				NULL);
			if (err==NULL){
				printf("in WriteFile error: %d.", GetLastError);
				exit(3);
			}
			counter=counter+(int)numWritten;
		}
	}while( numRead!=0);

	printf("Total number of bytes received: %d\n", counter);
	err=CloseHandle(writetofile);
	if (err==NULL){
		printf("in close writetohandle error: %d.", GetLastError);
		exit(5);
	}
}

	//====================================================
	//	START:	Upload Function 
	//	Please refer to the documentation of
	//	download function in server.cpp
	//====================================================
void upload(SOCKET &uploadSocket)
{
	//===================================
	HANDLE	filehandle;
	char moveBuffer[1100];
	char sNumRead[3];
	unsigned long numRead;
	int j=3, err, counter=0;

	filehandle=CreateFile(
		loadDir,
		GENERIC_READ,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	if (filehandle==INVALID_HANDLE_VALUE){
		printf("in READHANDLE error: %d.\n", GetLastError);
		exit(1);
	}

	//===================================
		do {
		//======================================
		err=ReadFile(
			filehandle,
			moveBuffer,
			100,
			&numRead,
			NULL);

		if (err==NULL){
			printf("in ReadFile error: %d.\n", GetLastError);
			exit(3);
		}
		
		_ultoa(numRead, sNumRead, 10);
		
		err=send(uploadSocket, sNumRead, j,0);
		if (err==SOCKET_ERROR) {
			printf("In send numRead, Client error: %d\n",WSAGetLastError());
			exit(10);
		}
		
		if (numRead!=0) {

			err=send(uploadSocket, moveBuffer, numRead,0);
			if (err==SOCKET_ERROR) {
				printf("In send moveBuffer, Client error: %d\n",WSAGetLastError());
				exit(11);
			}
			counter=counter+(int)numRead;
		}
		//======================================
	}while(numRead!=0);

	printf("Total amount of bytes transfered: %d\n", counter);
	
		err=CloseHandle(filehandle);
	if (err==NULL){
		printf("in close filehandle error: %d.", GetLastError);
		exit(4);
	}
}

	//===============================================================
	//	START:	load Function 
	//	This function tells the server side what to do, download
	//	or upload or quit, which file or folder to work on, 
	//	according to what is choose in display. 
	//===============================================================
void load(int i, SOCKET &loadSocket)
{
	int err, idLen;
	char sIdLen[3];
	char itemId[10], itemName[50], itemDir[50], itemComm[100];
	char uploadFileName[50];

	// get what the current item is, especially the index number
	currItem.getRecord(itemId, itemName, itemDir, itemComm);
	idLen=strlen(itemId);
	_itoa(idLen, sIdLen, 10 );

	// if the user chooses to download, and the record is a file, then do download
	if (i==1 && strcmp(itemComm, "file")==0) {
		//====================================
		// This part is repeated in else, instead of being
		// put before the if statement. It's because this 
		// structure guarantees that the itemId is sent only
		// when the user is making right choices.
		err=send(loadSocket, sIdLen, 3, 0);
		if (err==SOCKET_ERROR) {
			printf("In send numRead, Client error: %d\n",WSAGetLastError());
			exit(10);
		}
		err=send(loadSocket, itemId, idLen, 0);
		if (err==SOCKET_ERROR) {
			printf("In send numRead, Client error: %d\n",WSAGetLastError());
			exit(10);
		}
		//=====================================


		printf("Please enter download destination path, including FILE NAME.\n");
		printf("It's VERY IMPORTANT you use double back slashes!\n");
		printf("(Example: c:\\\\temp\\\\file.cpp)\n");
		printf("Please enter: ");
		gets(loadDir);
		download(loadSocket);
	} else if (i==2 && strcmp(itemComm, "folder")==0) {
		//==========================================
		err=send(loadSocket, sIdLen, 3, 0);
		if (err==SOCKET_ERROR) {
			printf("In send numRead, Client error: %d\n",WSAGetLastError());
			exit(10);
		}
		err=send(loadSocket, itemId, idLen, 0);
		if (err==SOCKET_ERROR) {
			printf("In send numRead, Client error: %d\n",WSAGetLastError());
			exit(10);
		}
		//===============================================================

		printf("Please enter a name for your file: ");
		gets(uploadFileName);

		idLen=strlen(uploadFileName);
		_itoa(idLen, sIdLen, 10 );

		err=send(loadSocket, sIdLen, 3, 0);
		if (err==SOCKET_ERROR) {
			printf("In send numRead, Client error: %d\n",WSAGetLastError());
			exit(10);
		}
		err=send(loadSocket, uploadFileName, idLen,0);
		if (err==SOCKET_ERROR) {
			printf("In send numRead, Client error: %d\n",WSAGetLastError());
			exit(10);
		}

		printf("Please enter upload source file directory, including FILE NAME.\n");
		printf("It's VERY IMPORTANT you use double back slashes!\n");
		printf("Example: c:\\\\temp\\\\file.cpp\n");
		printf("Please enter: ");
		gets(loadDir);
		upload(loadSocket);
	}else if (i==0) {
		// if the user chooses to quit, 0 is sent to the server side
		strcpy(itemId, "0");
		err=send(loadSocket, sIdLen, 3, 0);
		if (err==SOCKET_ERROR) {
			printf("In send numRead, Client error: %d\n",WSAGetLastError());
			exit(10);
		}
		err=send(loadSocket, itemId, idLen, 0);
		if (err==SOCKET_ERROR) {
			printf("In send numRead, Client error: %d\n",WSAGetLastError());
			exit(10);
		}

	} else {
		printf("Your request cannot be processed. Here are 3 possible reasons:\n");
		printf("1. You are asking to download a folder.\n");
		printf("2. You are asking to upload to a file.\n");
		printf("3. There are some mistake in the record itself.\n");
	}
}


	//====================================================
	//	START:	Functions for itemRecord Maintainance
	//====================================================
void create (void) 
{
	char itemId[10];
	for (int i=1; i<=10; i++) {
		_itoa(i, itemId, 10);
		items[i].iniRecord(itemId);
	}
}

void retrieve (void)
{
	FILE *retrieveHandle;
	char itemId[10], itemName[50], itemDir[50], itemComm[100];
	retrieveHandle=fopen("record.txt", "r");
	
	for (int i=1; i<=10; i++) {
		fscanf(retrieveHandle, "%s\n%s\n%s\n%s\n", itemId, itemName, itemDir, itemComm);
		items[i].setRecord(itemId, itemName, itemDir, itemComm);
	}
	fclose(retrieveHandle);
	printf("\nFile Retrieved.\n");
}

void display (SOCKET &displaySocket)
{
	char command[10];
	int i, j=1;

	do {
		items[j].displayRecord();
		currItem=items[j++];
		printf("\n0 - quit    1 - download   2 - upload    3 - next record\n");
		printf("Please Enter(0 - 3 ): ");
		gets(command);
		i=atoi(command);
		switch (i) {
			case 0: 
			case 1: 
			case 2: load(i, displaySocket);  break;
			case 3:	break;
		default:
			printf("Wrong commands used.\n");
			break;
		}
		if(j==11) j=j-10;	//always loop the display from item[1] to item[10]
	} while (i!=0);
}
	//====================================================
	//	END:	Functions for itemRecord Maintainance
	//====================================================