/** @file * \brief Fichero de implementación de un cliente * \author Imanol Barba Sabariego * \date 13/06/2013 * * En este fichero se implementa un cliente para poder usar con el servidor creado, usando la clase Socket. */ #include "client.h" using namespace std; bool connected, finished; //! Método para terminar el cliente /*! Este método se usa para terminar el cliente immediatamente en el caso que el servidor cierre la conexión de forma inesperada, capturando el signal SIGPIPE. */ void exitClient(int signal/*!> port;*/ cout << "Nickname: "; getline(cin,nick); host = "localhost"; port = 3001; try { s.Create(); s.Connect(host,port); cout << "Connected" << endl; connected = true; s << nick; s >> response; while(response == "CHATNICKINVALID") { cout << "Spaces not allowed in nicknames, please enter another nickname: "; getline(cin,nick); s << nick; s >> response; } while(response == "CHATNICKEXIST") { cout << "Nickname in use, please enter another nickname: "; getline(cin,nick); s << nick; s >> response; } while(response == "CHATFULL") { cout << "Chatroom is full, please wait..." << endl; s.Close(); return false; } if(response != "CHATOK") { cout << "Error: " << response << endl; return false; } } catch(SocketException& e) { cout << e.description() << endl; exit(-1); } return true; } void* sendThread(void* args) { string send; struct thread_args *t_arg = (struct thread_args*)args; while(connected) { cout << "> "; getline(cin,send); if(cin.eof()) { send = "/exit"; } try { *(t_arg->s) << send; if(send == "/disconnect" || send == "/exit") { break; } } catch(SocketException& e) { cout << e.description() << endl; } } killThread(t_arg); } void* recvThread(void* args) { string recv; struct thread_args *t_arg = (struct thread_args*)args; while(true) { try { *(t_arg->s) >> recv; } catch(SocketException &e) { connected = false; cout << e.description() << endl; (t_arg->s)->Close(); break; } if(recv == "DISC_OK") { cout << "Disconnecting" << endl; connected = false; pthread_cond_signal(t_arg->condition); break; } else if(recv == "EXIT_OK") { cout << "Exiting" << endl; connected = false; finished = true; pthread_cond_signal(t_arg->condition); break; } else { cout << recv << endl; } } killThread(t_arg); } //! Método principal del cliente /*! Este método inicializa el Socket, establece la conexión y realiza las acciones que se le hayan programado para comunicarse con el servidor.*/ int main() { signal(SIGPIPE, exitClient); Socket s; connected = finished = false; pthread_mutex_t mutex; pthread_mutex_init(&mutex,0); pthread_cond_t condition; pthread_cond_init(&condition,0); thread_args *sArgs = new thread_args; thread_args *rArgs = new thread_args; pthread_t recv, send; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); int retries = 3; while (!finished) { while(!connect(s)) { if((--retries) <= 0) { cout << "Exiting" << endl; exit(-1); } cout << "Couldn't connect to chatroom, retrying..." << endl; } pthread_mutex_lock(&mutex); sArgs->mutex = &mutex; sArgs->condition = &condition; sArgs->s = &s; rArgs->mutex = &mutex; rArgs->condition = &condition; rArgs->s = &s; pthread_create(&send,&attr,sendThread,(void *)sArgs); pthread_create(&recv,&attr,recvThread,(void *)rArgs); while(connected) { pthread_cond_wait(&condition,&mutex); } pthread_mutex_unlock(&mutex); pthread_join(recv,NULL); pthread_join(send,NULL); s.Close(); } pthread_cond_destroy(&condition); pthread_mutex_destroy(&mutex); } /* TODO * * CTRL+C */