Files

173 lines
5.9 KiB
C++

#include "ChatClient.h"
ChatClient::ChatClient(int port_number, string hostname) {
// Set the port number and hostname based on the constructor inputs
this->__port_number = port_number;
this->__host_name = hostname;
// Set flags to default values
this->__run_flag = true;
this->__set_user_handle_flag = true;
this->__setup_client_connection_flag = true;
this->__chat_with_server_flag = true;
// Print out the welcome screen
cout << "########################################" << endl;
cout << " Chat Client - Version 1.0 " << endl;
cout << " Written by Corwin Perren " << endl;
cout << "########################################" << endl;
}
void ChatClient::set_handle(){
// Ask the user for their handle
string handle;
cout << "Please enter your desired handle (10 characters max): ";
getline(cin, handle);
// Pull out a 10 character substring to make sure we don't go over the limit
handle = handle.substr(0, 10);
// Set the user's handle and printout
this->__user_handle = handle;
cout << "Handle set to: " << handle << "." << endl;
cout << "########################################" << endl;
}
void ChatClient::setup_connection(){
// Print out who we're connecting to
cout << "\n########################################" << endl;
cout << "Attempting to connect to \"" << this->__host_name << "\" on port " << this->__port_number << "." << endl;
struct sockaddr_in serv_addr;
struct hostent *server;
// Create a new Internet TCP socket file descriptor
this->__inet_file_descriptor = socket(AF_INET, SOCK_STREAM, 0);
// Make sure it was made successfully
if(this->__inet_file_descriptor < 0 ){
cout << "ERROR: Error opening socket. Exiting..." << endl;
this->__run_flag = false;
return;
}
// Translate the input host name to usable struct by the library
server = gethostbyname(this->__host_name.c_str());
// Verify that this worked. Will fail if the host doesn't exist
if(server == NULL){
cout << "Host does not exist. Exiting..." << endl;
this->__run_flag = false;
return;
}
// Empty the sockaddr struct
bzero((char *) &serv_addr, sizeof(serv_addr));
// Set the connection type
serv_addr.sin_family = AF_INET;
// Copy over the connection information from gethostname above
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
// Set the port
serv_addr.sin_port = htons(this->__port_number);
// Attempt to open the file descriptor with this connection information
int connection_result = connect(this->__inet_file_descriptor, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
// Let the user know if this failed
if(connection_result < 0){
cout << "ERROR: Error connecting to server. Please check host and port. Exiting..." << endl;
this->__run_flag = false;
return;
}
// We made it here, so success! Connected!
cout << "Connection to server successful!" << endl;
cout << "Ready to chat. You send first!" << endl;
cout << "########################################" << endl;
}
void ChatClient::chat_with_server(){
int result;
// Reset variables and print out user's handle for message prompt
string handle_message(this->__user_handle + "> ");
string user_message;
cout << handle_message;
// Read in the user's message
getline(cin, user_message);
// Make a complete version of the message to send that has their handle
string full_message(handle_message + user_message);
// Write this data to the server
result = write(this->__inet_file_descriptor, full_message.c_str(), strlen(full_message.c_str()));
// Let the user know if sending failed
if(result < 0){
cout << "ERROR: Error sending message. Connection may have been lost. Exiting..." << endl;
this->__run_flag = false;
return;
}
// If the user sent the quit message, close the socket and exit the program
if(user_message.find("\\quit") != string::npos){
close(this->__inet_file_descriptor);
this->__run_flag = false;
cout << "Closed connection with server!" << endl;
return;
}
// Empty a receive buffer
char buffer[1025];
bzero(buffer, 1025);
// Read in a message from the server
result = read(this->__inet_file_descriptor, buffer, 1024);
// If this failed, let the user know
if(result < 0){
cout << "ERROR: Error sending message. Connection may have been lost. Exiting..." << endl;
this->__run_flag = false;
return;
}
// Convert the received byte array to a string
string received_message(buffer);
// Check if the message from the server included the quit message. If so
// close the socket and exit the program
if(received_message.find("\\quit") != string::npos){
close(this->__inet_file_descriptor);
this->__run_flag = false;
cout << "Server closed connection!" << endl;
return;
}
// If this was a normal message, print it to the screen
cout << received_message << endl;
}
void ChatClient::run(){
// This is the main processing loop for the chat client. It starts by
// getting the user's handle, then attempts to open a connection to the
// server. If these are successful, then the user can chat with the server
// until either the server of client quits.
while(this->__run_flag){
if(this->__set_user_handle_flag){
this->set_handle();
this->__set_user_handle_flag = false;
}else if(this->__setup_client_connection_flag){
this->setup_connection();
this->__setup_client_connection_flag = false;
}else if(this->__chat_with_server_flag){
this->chat_with_server();
}
}
}