int main(int argc, char **argv) { int ds=crea_Socket("10.42.0.1", 1725); inviaMessaggio(ds,"ciao",4); chiudiSocket(ds); }
/** * Funzione che avverte il server del logout del client */ void avvisaServer() { messaggio* logout = messaggioConstructor(clientID, LOGOUT_AL_SERVER); inviaMessaggio(scriviAlServer, logout); messaggioDestructor(logout); }
/** * Funzione avviata come thread per ascoltare l'input utente da terminale ed eseguire i comandi impartiti * @param arg * @return */ void * inputUtenteClient(void* arg) { /*Come prima cosa, stampa il messaggio di help, che riporta i comandi disponibili*/ printHelp(false); /*Struct che permette di comprendere il tipo di comando impartito*/ comando c; /*Struct che contiene i dati inseriti in input dall'utente, come la risposta o il nome*/ data d; do { /*Chiamata bloccante in attesa di input utente, ritorna il comando impartito e inserisce eventuali dati nella struct d*/ c = leggiInput(&d); switch (c) { /*In base al comando impartito, agisco di conseguenza*/ case RISPOSTA: { //Se l'input è una risposta E sono connesso a una partita, allora cerco di inviarla if (connesso) { /*Stampo a schemo la risposta inserita dall'utente, per avere un feedback visuale*/ StampaRispostaInviata(d.risposta); messaggio* msg = messaggioConstructor(clientID, INVIA_RISPOSTA); if (testing) { /*Introduciamo un po' di latenza variabile sulle risposte dei client al server in modalità testing /*Per non sovvraccaricare la FIFO e poter controllare l'andamento del testing, senza essere sommersi da troppe print di informazione*/ struct timespec intervallo, intervallo2; intervallo.tv_sec = 0; intervallo.tv_nsec = 200000000 + 100000000 * (rand() % 30); nanosleep(&intervallo, &intervallo2); /*I client hanno una percentuale casuale di indovinare la risposta*/ int giusto = rand() % 100; if (giusto >= 10) msg->risposta = d.risposta; else msg->risposta = d.risposta + giusto; } else { msg->risposta = d.risposta; } inviaMessaggio(scriviAlServer, msg); messaggioDestructor(msg); } } break; case LOG_EXIT: /*Il client vuole uscire dalla modalità di log*/ { if (connesso) /*Se sono connesso, mostra la schermata di default con il grafico dei punteggi*/ SetGUIMode(STANDARD_CLIENT); else /*Se non sono connesso, mostra la schermata di login, chiedente il nome giocatore*/ SetGUIMode(LOGIN_CLIENT); } break; case HELP: { /*L'utente ha chiesto la lista di comandi disponibili*/ printHelp(false); } break; case NOME: { /*L'utente ha inserito una stringa, che devo usare come nome A questo punto posso richiedere la partecipazione al server, se non sono già connesso*/ if (!connesso) { strcpy(name, d.nome); /*Richiedo la partecipazione al server*/ messaggio* m = messaggioConstructor(clientID, RICHIESTA_PARTECIPAZIONE); sprintf(m->pathFifo, "%s", clientFifo); sprintf(m->nomeClient, "%s", d.nome); inviaMessaggio(scriviAlServer, m); messaggioDestructor(m); } else { /*Sono connesso al server, ma il giocatore ha inserito una stringa che non posso valutare come nome, essendo già connesso al server*/ sprintf(msgTmp, "%s\n", "Input non valido"); aggiungiMessaggio(msgTmp, true, ANSI_COLOR_RED); } } break; case ERRORE: /*Il giocatore ha inserito un comando che non riesco ad interpretare come valido*/ { sprintf(msgTmp, "%s\n", "Input non valido"); aggiungiMessaggio(msgTmp, true, ANSI_COLOR_RED); } break; default: break; } /*Aggiorna la schermata dopo aver processato l'input ricevuto*/ updateScreen(); /*Rimane in ascolto di input utente fino a quando non ricevo il comando di chiusura*/ } while (c != CHIUSURA); /*Chiudo il client*/ cleanupClient(0); return NULL; }
/*Funzione chiamata dal main per avviare il processo come client*/ int initClient() { /*Segnali di chiusura*/ signal(SIGSEGV, cleanupClient); signal(SIGABRT, cleanupClient); /*Chiusura terminale*/ signal(SIGHUP, cleanupClient); signal(SIGTERM, cleanupClient); /*Ctrl-C*/ signal(SIGINT, cleanupClient); /*Ctrl-Z*/ signal(SIGTSTP, cleanupClient); signal(SIGSTOP, cleanupClient); /*Ctrl-\*/ signal(SIGQUIT, cleanupClient); /*Segnali di chiusura FIFO, se perdo collegamento con il server brutalmente*/ signal(SIGPIPE, serverDisconnesso); /*Inizializzo GUI*/ if (testing) { SetGUIMode(TESTING_CLIENT); } else { calcolaLarghezzaSchermo(0); SetGUIMode(LOGIN_CLIENT); } updateScreen(); /*Controllo se esiste un server*/; int exist = access(SERVERPATH, F_OK); //Se non esiste un server, lo notifico a schermo e chiudo if (exist == -1) { SetGUIMode(EXIT_CLIENT); sprintf(msgTmp, "%s\n", "Il server non è attivo!"); aggiungiMessaggio(msgTmp, true, ANSI_COLOR_RED); return -1; } /*Apro la mia FIFO da cui ascolterò i messaggi dal server*/ sprintf(clientFifo, "%s%i", CLIENTFIFO, getpid()); ascoltoDalServer = creaFifoLettura(clientFifo); if (ascoltoDalServer == -1) { /*Se non riesco ad aprire la FIFO, abortisco*/ sprintf(msgTmp, "%s\n", "Errore nell'apertura del client"); aggiungiMessaggio(msgTmp, true, ANSI_COLOR_RED); cleanupClient(0); exit(EXIT_FAILURE); } /*Apro la FIFO per contattare il server*/ scriviAlServer = creaFiFoScrittura(SERVERPATH); if (scriviAlServer == -1) { sprintf(msgTmp, "%s\n", "Errore nell'apertura del client"); aggiungiMessaggio(msgTmp, true, ANSI_COLOR_RED); cleanupClient(0); } if (!testing) { /*Faccio partire il thread di ascolto dei messaggi da terminale, se non sono in modalità testing*/ pthread_t threadID; pthread_create(&threadID, NULL, &inputUtenteClient, NULL); } else { /*Sono in modalità testing. Come prima cosa, rihiedo la partecipazione al server, * e solo quando avrò ricevuto il suo messaggio di accettazione avvierò il thread di lettura input utente*/ messaggio* partecipazione = messaggioConstructor(0, RICHIESTA_PARTECIPAZIONE); sprintf(partecipazione->pathFifo, "%s", clientFifo); char nome [MAXNAME]; /*Leggo il nome da input utente, che fa riferimento ad uno dei file di assets*/ scanf("%s", nome); sprintf(partecipazione->nomeClient, "%s", nome); inviaMessaggio(scriviAlServer, partecipazione); messaggioDestructor(partecipazione); } /*Ascolto FIFO da cui riceverò i messaggi dal server. Il thread principale rimane all'interno di questo metodo*/ ascoltaServer(); cleanupClient(0); return 0; }