mirror of
https://github.com/caperren/school_archives.git
synced 2025-11-09 21:51:15 +00:00
173 lines
5.9 KiB
C++
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();
|
|
}
|
|
}
|
|
|
|
}
|