External Exam Download Resources Web Applications Games Recycle Bin

TcpClient.cpp

------------------------------------
TcpConsole Class Implementation File
------------------------------------*/

#include "stdafx.h"
#include "TcpClient.h"

/***********
constructor:
************/
TcpConsole::TcpConsole(){
	Console::WriteLine("***** Restaurant Booking Client *****\n");
	expecting_unknown_length_answer = false;
};

/**********
destructor:
***********/
TcpConsole::~TcpConsole(){
	//if no flag on connection:
	if(!failedFlag){
		//Mark the TcpClient instance as disposed, and request the socket to close the TCP connection:
		server->Close();
		Console::WriteLine("Ended connection with server.");
		//Clean up dynamically allocated resources:
		delete server; delete writer; delete reader; delete write_buffer; delete read_buffer;
	}
};

/*************************************************
connect: using a connection oriented socket (TCP),
allows client console to connect to TCP Server.
**************************************************/
bool TcpConsole::connect(){
	try //and make this connection:
		{
		/*Following example is using IP 127.0.0.1 for standard loopback connection
		during development (this MUST be changed to server IP upon publishing).
		Port 12345 is port being listened by server (specified in ReservationServer.cpp)
		- thus client MUST use this port or server will actively refuse the connection.
		TCP chosen as protocol due to its guaranteed delivery of payload (data)
		unlike media / gaming applications primarily concerned with speed (where UDP would be of greater use).
		Further discussion of this found in various materials on the web.*/
		server = gcnew TcpClient("127.0.0.1", 12345);
		/*Using a stream reader and writer to make client / server
		communication easier with server through a "base stream" of strings.
		GetStream returns a Networkstream object from the current server,
		from which the Stream Reader and Writer are created:*/
		writer = gcnew StreamWriter(server->GetStream());
		reader = gcnew StreamReader(server->GetStream());
		}	
	//...and if this connection fails:
	catch (SocketException^ se)
		{
		//Display the error message thrown:
		Console::WriteLine("Could not connect to server: "+se->Message+"\nHit enter to exit.");
		//give users chance to read message:
		Console::ReadLine();
		failedFlag = true;
		return false;
		}
	failedFlag = false;
	return true;
};

/************************************************
read_block: used to read from the input base
stream until there is nothing left in the stream.
*************************************************/
void TcpConsole::read_block(){
	//while there is another available character in the input stream, write it:
	while (reader->Peek()>=0)Console::WriteLine(reader->ReadLine());
	//once all characters have been read, clear internal buffer:
	this->reader->DiscardBufferedData();
};

/*********************************
menu_options: provides console UI.
**********************************/
void TcpConsole::menu_options(){
	//MENU:
	Console::WriteLine("\nOptions:");
	Console::WriteLine("hit '1' to request the number of places currently available;");
	Console::WriteLine("hit '2' to make a booking;");
	Console::WriteLine("hit '3' to cancel a previous booking;");
	Console::WriteLine("hit 'q' to quit.");
	Console::WriteLine();
	Console::Write("Your Choice: ");
};

/****************************************************************************
prepare_request: accepts a String^ argument which contains the users request,
and concatenates all information supplied into a single line ready for the
write buffer.  Finally, determines length of response.
*****************************************************************************/
void TcpConsole::prepare_request(String^ msg){
	write_buffer="";

	//1. display bookings:
	if(msg->Equals ("1")) {write_buffer="1"; expecting_unknown_length_answer = false;}
	
	//2. make booking:
	if (msg->Equals ("2")){
		write_buffer="2,";
		Console::Write("Which sitting number? eg. '1': ");
		write_buffer=write_buffer+Console::ReadLine();
		Console::Write("What booking name? eg. 'George': ");
		write_buffer=write_buffer+","+Console::ReadLine();
		Console::Write("How many seats? eg. '2': ");
		write_buffer=write_buffer+","+Console::ReadLine();
		Console::WriteLine("\nProcessing... please be patient...\n");
		expecting_unknown_length_answer = true;
	}
		
	//3. cancel booking:
	if (msg->Equals ("3")){
		write_buffer="3,";
		Console::Write("What was your UNIQUE RESERVATION KEY? eg. '82HARRY3': ");
		write_buffer=write_buffer+Console::ReadLine();
		Console::WriteLine("\nProcessing... please be patient...\n");
		expecting_unknown_length_answer = false;
	}
};

/****************************************************************
send_request: sends underlying streamwriter buffer to the server.
*****************************************************************/
void TcpConsole::send_request(){
	/*just incase there is anything residual, as after flushing the write buffer, 
	a response could be expected at minimum instantly:*/
	reader->DiscardBufferedData();
	//send write buffer to the stream writer and flush it (send it to the server):
	writer->WriteLine(write_buffer);
	writer->Flush();
};

/***************************************************************************
process_response: determines whether response is a fixed or variable length.
****************************************************************************/
void TcpConsole::process_response(){
	if(!expecting_unknown_length_answer) read_block(); else	read_unknown_length();		
};

/*********************************************************************
read_unknown_length: continues reading stream until encountering "EOM"
which signals the end of message.
**********************************************************************/
void TcpConsole::read_unknown_length(){
	for(;;){
			read_buffer="";
			read_buffer=reader->ReadLine();
			if(read_buffer=="EOM")break;
			//for unique reservation key, set console colour to magenta so it stands out:
			if(read_buffer=="EXPECT_KEY") Console::ForegroundColor::set(System::ConsoleColor::Magenta); else Console::WriteLine(read_buffer);
			}
	Console::ForegroundColor::set(System::ConsoleColor::Gray);
	this->reader->DiscardBufferedData();
};